网络编程基础部分整理
Ip地址:InetAddress
- 网络中设备的标识:不宜记忆,可以用主机(服务器)名
- 本地回环地址:127.0.0.1 主机名:localhost
- 端口号:用于标识进程的逻辑地址,不同进程的标识
- 有效端口:0~ 65535,其中0~1024被系统使用或者保留端口,也有的端口已经被占用了
- 传输协议:TCP(传输控制协议),UDP(数据报文包协议)
- 网址:http//:sina.com.cn
tcp,udp
(协议http//:+ 主机名sina + 通用域名com(commercial),中国的cn)
package internet_Adress;
import java.net.InetAddress;
import java.net.UnknownHostException;
/**
* 获取本地主机的IP地址和主机名
* 获取其他主机地址和ip地址时,会遇到解析失败的情况。
*/
public class InetAddressDemo {
public static void main(String[] args) throws UnknownHostException {
//ip地址对象 InetAddress
//获取本地主机对象
InetAddress ip1=InetAddress.getLocalHost();
//输出ip地址和主机名
System.out.println(ip1.getHostAddress()+"------"+ip1.getHostName());
//根据ip地址获取该地址的主机名
//注意: 如果是本地局域网下的非本机ip 主机名可能无法获取,因为需要进行解析
InetAddress ip2=InetAddress.getByName("42.224.252.27");
//根据主机名获取ip地址
InetAddress ip3=InetAddress.getByName("DESKTOP-HVR3SSG");
System.out.println(ip2.getHostAddress()+"------"+ip2.getHostName());
System.out.println(ip3.getHostAddress()+"------"+ip3.getHostName());
}
}
解析
- 新浪网首页的访问,主机:http//:www.sina.com.cn
- 新浪的新闻页面访问,子主机:http//:news.sina.com.cn
- 新浪的运动体育访问,子主机:http//:sports.sina.com.cn
比如
- 客户端输入:http//:www.sina.com.cn
然后通过解析操作,去本地查表 - 本地查表路径:C:\Windows\System32\drivers\etc\hosts
- 当然本地主机存储的域名和主机名有限
- 宽带服务商提供了一个叫做DNS域名服务器,并且DNS服务器也有一个域名,当你连上宽带网线时就直接访问的是宽带服务商的域名服务器。
-
获取到ip地址后返回给本地主机再访问到该IP地址的网站上。
图片.png
端口号
给确定软件的一个网络数字标识,必须保证唯一性。
图片.png传输协议
UDP
- 将数据及源和目的封装成数据包中,不需要建立连接
- 每个数据报的大小在限制在64k内
- 因为不需要连接,所以是不可靠的协议
- 不需要建立连接,速度便很快。
TCP - 建立连接,形成传输数据的通道
- 在连接中进行大数据量的传输
- 通过三次握手完成连接,是可靠协议
- 必须建立连接,效率会稍低。
socket通信
- Socket就是为网络服务提供的一种机制
- 通信的两端都有Socket :server client
- 网络通信其实就是Socket间的通信
- 数据在两个Socket间通过IO传输
UDP的发送端
package udp_socket;
import java.io.IOException;
import java.net.*;
/**
* 通过查阅文档,了解到用于UDP传输协议的对象是DatagramSocket
* 通过UDP的协议发送一段文本数据
* 思路:
* 1.需要将建立UDP的socket,它具备发送或者接收功能。
* 2.将数据封装到数据包中。数据包对象是DatagramPackage
* 3.使用socket对象的send方法将数据包发送出去。
* 4.关闭资源。
*/
public class Udp_Send {
public static void main(String[] args) throws IOException {
System.out.println("UDP发送端 run");
//创建socket对象
DatagramSocket ds = new DatagramSocket();
//创建数据资源
String bytes = "你好呀!123 java111118 98489415481 2854969541";
byte[] bytes1 = bytes.getBytes();
DatagramPacket dp = new DatagramPacket(bytes1, bytes.length(), InetAddress.getByName("115.50.18.31"), 10000);
ds.send(dp);
ds.close();
}
}
UDP的接收端
package udp_socket;
import java.io.IOException;
import java.net.DatagramPacket;
import java.net.DatagramSocket;
/**
* 定义一个udp的接收端。接收发送过来的数据。并显示在屏幕上
* 思路:
* - 1.先创建udp 的socket服务,并且指定同一端口
* - 2.接收数据之前先创建数据包成byte数组
* - 3.定义数据包
* - 4.通过数据包对象获取数据包的内容,发送端的ip,发送端的端口,发送过来的数据。
* - 5.将接收端IP 端口号,内容 打印在屏幕上
* - 6.最后关闭资源。
*/
public class Udp_Receive {
public static void main(String[] args) throws IOException {
System.out.println("UDP的接收端 run");
DatagramSocket ds=new DatagramSocket(10000);
byte [] bytes=new byte[1024];
DatagramPacket dat=new DatagramPacket(bytes,bytes.length);
ds.receive(dat);
String ip=dat.getAddress().getHostAddress();
int port=dat.getPort();
String test=new String(dat.getData(),0,dat.getLength());
System.out.println(ip+"----"+port+"------"+test);
//115.50.18.31----61651------你好呀!123 java111118 98489415481 28
ds.close();
}
}
键盘录入
- 使用高效缓冲流对象创建键盘录入对象
读取字符串后转化为字节数组 - 循环读取并发送数据
UDP发送端
package udp_socket2.udp_socket;
import java.io.BufferedReader;
import java.io.FileInputStream;
import java.io.IOException;
import java.io.InputStreamReader;
import java.net.DatagramPacket;
import java.net.DatagramSocket;
import java.net.InetAddress;
import java.nio.Buffer;
/**
* 通过查阅文档,了解到用于UDP传输协议的对象是DatagramSocket
* 通过UDP的协议发送一段文本数据
* 思路:
* 1.需要将建立UDP的socket,它具备发送或者接收功能。
* 2.将数据封装到数据包中。数据包对象是DatagramPackage
* 3.使用socket对象的send方法将数据包发送出去。
* 4.关闭资源。
*/
public class Udp_Send2 {
public static void main(String[] args) throws IOException {
System.out.println("UDP发送端 run");
//创建socket对象
DatagramSocket ds = new DatagramSocket();
BufferedReader bf=new BufferedReader(new InputStreamReader(System.in));
String line=null;
while ((line=bf.readLine())!=null){
if (line.equals("over")) {
break;
}
byte[] bytes=line.getBytes();
DatagramPacket dp = new DatagramPacket(bytes,bytes.length, InetAddress.getByName("115.50.18.31"), 10000);
ds.send(dp);
}
ds.close();
}
}
UDP接收端
package udp_socket2.udp_socket;
import java.io.IOException;
import java.net.DatagramPacket;
import java.net.DatagramSocket;
/**
* 定义一个udp的接收端。接收发送过来的数据。并显示在屏幕上
* 思路:
* - 1.先创建udp 的socket服务,并且指定同一端口
* - 2.接收数据之前先创建数据包成byte数组
* - 3.定义数据包
* - 4.通过数据包对象获取数据包的内容,发送端的ip,发送端的端口,发送过来的数据。
* - 5.将接收端IP 端口号,内容 打印在屏幕上
* - 6.最后关闭资源。
*/
public class Udp_Receive2 {
public static void main(String[] args) throws IOException {
System.out.println("UDP的接收端 run");
DatagramSocket ds=new DatagramSocket(10000);
while (true) {
byte[] bytes = new byte[1024];
DatagramPacket dat = new DatagramPacket(bytes, bytes.length);
ds.receive(dat);
String ip = dat.getAddress().getHostAddress();
int port = dat.getPort();
String test = new String(dat.getData(), 0, dat.getLength());
System.out.println(ip + "----" + port + "------" + test);
}
//ds.close();
}
}
UDP群聊
192.168.1.3
其中的3表示该局域网下的编号为3的主机
如果将3变成255,将会把发送的信息发给该网段的所有0~255(0不是一台主机,255也不包含)内的所有主机。实现了广播操作-----群聊
UDP发送端
package udp_chat;
import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStreamReader;
import java.net.DatagramPacket;
import java.net.DatagramSocket;
import java.net.InetAddress;
/**
* 创建发送端,并实现Runnable接口
* 并且将socket发送端对象使用构造器传递
* 实现run()方法,将键盘录入的信息转化为字节数组,然后转化为数据报文包发送
*/
public class Send implements Runnable {
private DatagramSocket ds;
private BufferedReader bf = null;
public Send(DatagramSocket ds) {
this.ds = ds;
}
@Override
public void run() {
try {
bf = new BufferedReader(new InputStreamReader(System.in));
String line;
while ((line = bf.readLine()) != null) {
byte[] bytes = line.getBytes();
DatagramPacket dp = new DatagramPacket(bytes, bytes.length, InetAddress.getByName("192.168.1.255"), 10000);
ds.send(dp);
if (line.equals("886")) {
break;
}
}
} catch (IOException e) {
}
ds.close();
}
}
UDP接收端
package udp_chat;
import java.io.IOException;
import java.net.DatagramPacket;
import java.net.DatagramSocket;
/**
* 接收端创建线程对象
* 也将Rece的对象中添加socket通信对象
* 同样实现run方法
* 并将数据接受后并打印
*/
public class Rece implements Runnable {
private DatagramSocket ds;
public Rece(DatagramSocket ds) {
this.ds = ds;
}
@Override
public void run() {
try {
while (true) {
byte[] bytes = new byte[1024];
DatagramPacket da = new DatagramPacket(bytes, bytes.length);
ds.receive(da);
String ip = da.getAddress().getHostAddress();
int port = da.getPort();
String test = new String(da.getData(), 0, da.getLength());
System.out.println(ip + "----" + port + "------" + test);
if (test.equals("886")) {
System.out.println(ip + "----退出聊天室");
}
}
} catch (IOException e) {
e.printStackTrace();
}
}
}
群聊测试类
package udp_chat;
import java.net.DatagramSocket;
import java.net.SocketException;
/**
* UDP实现群聊
* 思路:
* 这个操作既有发送,也有接收,需要两个线程
* 一个负责接收,一个负责发送
*/
public class TestChat {
public static void main(String[] args) throws SocketException {
//创建非共享的socket
DatagramSocket send = new DatagramSocket();
//接收端需要定义端口
DatagramSocket rece = new DatagramSocket(10000);
//实例化发送端
Send se = new Send(send);
//实例化接收端
Rece re = new Rece(rece);
//创建线程对象
Thread t1 = new Thread(se);
Thread t2 = new Thread(re);
//开启线程
t1.start();
t2.start();
}
}
TCP通信
TCP通信能实现两台计算机之间的数据交互,通信的两端,要严格区分为客户端(Client)与服务端(Server)。
两端通信步骤:
- 服务端程序,需要事先启动,等待客户端的连接。
- 客户端主动连接服务器端,连接成功才能通信。服务端不可以主动连接客户端。
两个类用于实现TCP通信程序
- 1.客户端: java.net.Socket 类表示。创建 Socket 对象,向服务端发出连接请求,服务端响应请求,两者建 立连接开始通信。
- 服务端: java.net.ServerSocket 类表示。创建 ServerSocket 对象,相当于开启一个服务,并等待客户端 的连接。
客户端TCP
package tcp_socket;
import java.io.IOException;
import java.io.OutputStream;
import java.net.Socket;
/**
* 需求:通过tcp传输将数据发送给服务器
* 思路:
* 1.建立tcp的客户端socket,明确服务端的地址和端口。
* 2.如果通道建立成功就会出现socket io流。
* 客户端需要做的就是获取socket流中的输出流将数据发送给目的服务器端。
* 3.通过socket输出流将数据发送。
* 4.关闭资源(只需要关闭socket即可)。
*/
public class SocketClient {
public static void main(String[] args) throws IOException {
Socket so=new Socket("192.168.1.3",10005);
OutputStream out = so.getOutputStream();
out.write("hello java".getBytes());
so.close();
}
}
//Exception in thread "main" java.net.ConnectException: Connection refused: connect
//由于未定义服务器端,连接失败,抛出异常。
TCP服务端
package tcp_socket;
import java.io.IOException;
import java.io.InputStream;
import java.net.ServerSocket;
import java.net.Socket;
/**
* 需求:获取客户端的数据并显示在屏幕上
* 思路:
* 1.创建服务器端的SeverSocket,明确端口,监听一个端口
* 2.获取socket 对象
* 3.服务器端只要获取连接过来的客户端就可以与指定的客户端通信了
* 4.通过获取客户端读取流对象读取客户端发来的数据
* 5.并显示在屏幕上
* 6.关闭资源。
*/
public class SocketServerDemo {
public static void main(String[] args) throws IOException {
System.out.println("服务器端 run");
//创建服务器端
ServerSocket ss=new ServerSocket(10003);
while(true){
//获取socket 对象
Socket s = ss.accept();
String ip = s.getInetAddress().getHostAddress();
System.out.println(ip+"----------connected");
//获取客户端的读取流对象
InputStream in = s.getInputStream();
//创建字节数组
byte [] bytes=new byte[1024];
//读取数据
int len = in.read(bytes);
//打印数据
System.out.println(new String(bytes,0,len));
//关闭客户端流资源
s.close();
}}
}
TCP客户端,服务端通信
- 客户端
package socket_TCP2;
import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
import java.net.Socket;
public class ClientSocketDemo {
public static void main(String[] args) throws IOException {
System.out.println("客户端启动......");
//创建Socket对象,并指定ip地址和端口号
Socket s=new Socket("192.168.1.3",9999);
//获取socket的写出流
OutputStream out=s.getOutputStream();
//写入数据给服务器
out.write("服务器,我来了".getBytes());
//获取服务器返还的数据的读取流对象
InputStream in = s.getInputStream();
//数组读取,并打印到屏幕上
byte [] bytes=new byte[1024];
int len = in.read(bytes);
String test=new String(bytes,0,len);
System.out.println(test);
//关闭资源
s.close();
}
}
- 服务器端
package socket_TCP2;
import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
import java.net.ServerSocket;
import java.net.Socket;
public class ServerSocketDemo {
public static void main(String[] args) throws IOException {
System.out.println("服务器端启动......");
//创建ServerSocket对象,并指定端口号
ServerSocket ss=new ServerSocket(9999);
while (true) {
//持续获取socket对象
Socket s = ss.accept();
//打印获取的socket对象的客户端IP地址
System.out.println(s.getInetAddress().getHostAddress()+"---------connected");
//获取服务端的读取流对象
InputStream in = s.getInputStream();
//读取客户端发来的数据
byte[] bytes = new byte[1024];
int len = in.read(bytes);
System.out.println(new String(bytes, 0, len));
//将服务端的数据回复给客户端
OutputStream out = s.getOutputStream();
out.write("客户端,我已经收到!".getBytes());
//关闭资源
s.close();
}
}
}
网友评论