网络编程 --- TCP和UDP协议
网络编程 — TCP和UDP协议
TCP通信
- TCP通信的概念
TCP协议
TCP协议是面向连接的通信协议,即在传输数据前先在发送端和接收端建立逻辑连接,然后再传输数据,它提供了两台计算机之间可靠无差错的数据传输。在TCP连接中必须要明确客户端与服务器端,由客户端向服务端发出连接请求,每次连接的创建都需要经过“三次握手”。第一次握手,客户端向服务器端发出连接请求,等待服务器确认,第二次握手,服务器端向客户端回送一个响应,通知客户端收到了连接请求,第三次握手,客户端再次向服务器端发送确认信息,确认连接。
- 构造方法
ServerSocket(int port) 创建绑定特定端口的服务器端口号(套接字)
- 常用方法
accept() 侦听并接受此套接字的连接,返回值是Socket类对象
getInetAddress() 返回次服务器套接字的本地地址,返回值是InetAddress对象
- Socket类的构造方法和普通方法
- 构造方法
Socket(String host, int port) 使用该构造方法在创建Socket对象时,会根据参数去连接在指定地址和端口上运行的服务器程序,其中参数host接收的是一个字符串类型的IP地址。
Socket(InetAddress address, int post) 接收一个InetAddress对象封装的IP地址连接到指定的端口号
- 常用方法
int getPort() 该方法返回一个int类型对象,该对象是Socket对象与服务器端连接的端口号
InetAddress getLocalAddress() 该方法用于获取Socket对象绑定的本地IP地址,并将IP地址封装成InetAddress类型的对象返回
void close() 该方法用于关闭Socket连接,结束本次通信。在关闭socket之前,应将与socket相关的所有的输入/输出流全部关闭,这是因为一个良好的程序应该在执行完毕时释放所有的资源
InputStream getInputStream() 该方法返回一个InputStream类型的输入流对象,如果该对象是由服务器端的Socket返回,就用于读取客户端发送的数据,反之,用于读取服务器端发送的数据
OutputStream getOutputStream() 该方法返回一个OutputStream类型的输出流对象,如果该对象是由服务器端的Socket返回,就用于向客户端发送数据,反之,用于向服务器端发送数据
简单的TCP通信Demo
- 代码准备 服务器端
public class MyServer {
public static void main(String[] args) {
try {
//创建服务器端对象,并指定连接的端口号
ServerSocket server = new ServerSocket(9090);
//侦听并接受此套接字的连接,返回Socket类对象
Socket socket = server.accept();
//读取客户端发送来的数据
InputStream is = socket.getInputStream();
byte[] bytes = new byte[1024];
int length = is.read(bytes);
//将数据转换成字符串,并打印到控制台
String thisData = new String(bytes, 0, length);
System.out.println(thisData);
//向客户端返回一条数据
OutputStream os = socket.getOutputStream();
byte[] bytes1 = "访问成功".getBytes();
os.write(bytes1,0,bytes1.length);
//关闭流
is.close();
os.close();
socket.close();
} catch (IOException e) {
e.printStackTrace();
}
}
}
- 客户端
public class MyClient {
public static void main(String[] args) {
//创建客户端对象,连接指定服务器的IP和端口号
try {
Socket socket = new Socket(InetAddress.getLocalHost().getHostAddress(),9090);
//向服务器端发送一条数据
OutputStream os = socket.getOutputStream();
byte[] bytes = "请求访问".getBytes();
os.write(bytes,0,bytes.length);
//接收服务器端返回来的数据
InputStream is = socket.getInputStream();
byte[] bytes1 = new byte[1024];
int length = is.read(bytes1);
//将返回来的数据转换为字符串并打印
String thisData = new String(bytes1, 0, length);
System.out.println(thisData);
//关闭流
os.close();
is.close();
socket.close();
} catch (IOException e) {
e.printStackTrace();
}
}
}
开启服务器客户端访问服务器打印结果:
服务器端:请求访问
客户端:访问成功
UDP通信
- UDP通信的概念
UDP是无连接通信协议,即在数据传输时,数据的发送端和接收端不建立逻辑连接。简单来说,当一台计算机向另外一台计算机发送数据时,发送端不会确认接收端是否存在,就会发出数据,同样接收端在收到数据时,也不会向发送端反馈是否收到数据。
由于使用UDP协议消耗资源小,通信效率高,所以通常都会用于音频、视频和普通数据的传输例如视频会议都使用UDP协议,因为这种情况即使偶尔丢失一两个数据包,也不会对接收结果产生太大影响。
但是在使用UDP协议传送数据时,由于UDP的面向无连接性,不能保证数据的完整性,因此在传输重要数据时不建议使用UDP协议。
-
在JDK中提供了两个类用于实现UDP程序
DatagramPacket类,该类的实例对象就相当于一个集装箱,用于封装UDP通信中发送或者接收的数据。
DatagramSocket类,该类的作用就类似于码头,使用这个类的实例对象就可以发送和接收DatagramPacket数据包
-
DatagramPacket的构造方法和普通方法
- 构造方法
DatagramPacket(byte[] buf,int length) 构造DatagramPacket,用来接收长度为length的数据包
DatagramPacket(byte[] buf,int length,InetAddress address,int post) 构造数据包,用来将长度为length的包发送到指定主机上的指定端口号
- 常用方法
getAddres() 返回某台机器的IP地址
getPost() 返回某台远程主机的端口号
getData() 返回数据缓冲区
getLength() 返回将要发送或接收到的数据长度
- DatagramSocket的构造方法和普通方法
- 构造方法
DatagramSocket() 构造数据报套接字并将其绑定到本地主机上任何可以端口
DatagramSocket(int post) 创建数据报套接字并将其绑定到本地主机上的指定端口- 常用方法
receive(DatagramPacket p) 接收数据报包
send(DatagramPacket p) 发送数据报包
简单的UDP通信Demo
- 代码准备 接收端
public class MyReceiving {
public static void main(String[] args) {
try {
//创建DatagramSocket对象(码头),并指定端口号
DatagramSocket socket = new DatagramSocket(4573);
//创建DatagramPacket对象(集装箱),将接收到的数据进行打包
byte[] bytes = new byte[1024];
DatagramPacket packet = new DatagramPacket(bytes,bytes.length);
//接收数据报包
socket.receive(packet);
//获取发送端发来的数据
byte[] data = packet.getData();
//获取数据的长度
int length = packet.getLength();
//查看主机IP为?
String ip = packet.getAddress().getHostAddress();
System.out.println("主机IP为:"+ip+" 发来的数据为:"+new String(data,0,length));
//关闭流资源
socket.close();
} catch (Exception e) {
e.printStackTrace();
}
}
}
- 发送端
public class MySender {
public static void main(String[] args) {
try {
//创建DatagramSocket码头,用来发送数据报包
DatagramSocket socket = new DatagramSocket();
//准备数据
byte[] bytes = "你好,世界".getBytes();
int length = bytes.length;
//创建DatagramPacket集装箱,将数据打包
DatagramPacket packet = new DatagramPacket(bytes,length, InetAddress.getByName(InetAddress.getLocalHost().getHostAddress()),4573);
//发送数据报包
socket.send(packet);
//关闭流资源
socket.close();
} catch (Exception e) {
e.printStackTrace();
}
}
}
向运行接收端,再运行发送端
运行结果:
接收端:主机IP为:192.168.1.35 发来的数据为:你好,世界