转载声明:文章来源https://blog.csdn.net/weixin_44821219/article/details/139392087
一、UDP
UDP概念
UDP(User Datagram Protocol)用户数据报协议,是一种无连接的传输层协议,位于OIS模型的传输层,用于在计算机网络上发送数据。UDP提供了一种以最少的协议机制向其他程序发送消息的过程。
UDP特点
UDP协议的特点包括无连接、不可靠、面向数据报等。UDP不保证数据包的可靠传输,没有确认、重传机制。UDP数据包是独立的数据单元,不依赖于之前或之后的数据包。应用层交给UDP的数据,UDP原样发送,不会拆分或合并。
无连接:UDP在发送数据前不进行连接,发送结束时也没有连接可以释放,这减少了开销和发送数据之前的时延。
尽最大努力交付:UDP不保证可靠交付,因此主机不维持复杂的连接状态。
面向报文:发送方的UDP对应用程序交下来的报文,再添加首部后就向下交付IP层。UDP对应用层交下来的报文,既不合并,也不拆分,而是保留这些报文的边界。接收方的UDP对IP层交上来的UDP用户数据报,在去除首部后就原封不动地交付上层的应用进程。
无拥塞控制:UDP适合于实时应用,如IP电话、实时视频会议等,这些应用要求源主机以恒定的速率发送数据,并且允许网络发生拥塞时丢失一些数据,却不允许数据有太大的时延。
支持多种通信模式:UDP支持一对一、一对多、多对一和多对多的交互通信。
首部开销小:UDP只有8个字节的首部,这使得它在需要快速传输的场景下非常有用。
UDP报文格式
UDP报文格式是UDP协议传输数据的基本结构,它包括UDP首部和数据部分。
首部字段:UDP首部字段总共有8个字节,分为4个部分,每部分两个字节。
源端口(Source Port):16位字段,指定发送端的端口号。如果发送方没有指定端口,则操作系统会随机分配一个临时端口。
目的端口(Destination Port):16位字段,指定接收端的端口号。这是必须字段,用于将数据报正确交付到接收方的应用程序。
长度(Length):16位字段,指定UDP报文的总长度,包括UDP首部和数据。如果数据部分不是偶数个字节,长度字段会加上一个填充字节以保证长度为8字节的倍数。最小为8,最大为64k(2^16)。
检验和(Checksum):16位字段,用于错误检测。它在发送前计算并填充,接收方在接收到数据报后会重新计算检验和以验证数据的完整性。如果检验和有误,UDP会丢弃该数据报。
伪首部(Pseudo Header):虽然伪首部不是UDP报文的一部分,但它在计算检验和时使用。
在计算检验和时,要在UDP用户数据报之前增加12个字的伪首部,这包括源地址、目的地址、置零域、协议字段和UDP长度。
源IP地址(Source Address):32位字段,指定发送方的IP地址。
目的IP地址(Destination Address):32位字段,指定接收方的IP地址。
置零域(Zero):8位字段,通常置为0。
协议字段(Protocol):8位字段,指定上层协议类型,对于UDP是17。
UDP长度(UDP Length):16位字段,与UDP首部中的长度字段相同,指定整个UDP数据报的长度。
数据部分:数据部分紧随UDP首部之后,它包含了实际要传输的数据。UDP不对数据部分进行任何处理,如合并或拆分数据包,它保持数据的边界不变。
UDP报文的这种格式设计使得UDP协议简单且高效,适用于那些对实时性要求高、可以容忍一定数据丢失的应用场景
二、UDP进行网络通信
客户端
1.创建InetSocketAddress对象封装本地ip和端口
2.创建DatagramSocket对象,将本机Address对象传入
3.创建InetSocketAddress对象封装目的ip和端口
4.封装DatagramPacket对象,传入发送内容及目的Address对象
5.发送packet
package udp.v1;
import java.io.IOException;
import java.net.*;
public class Client {
private String serverIp ;
private int port ;
public Client(String serverIp, int port) {
this.serverIp = serverIp;
this.port = port;
}
public static void main(String[] args) {
Client client = new Client("127.0.0.1",1238);
InetSocketAddress address = new InetSocketAddress(client.serverIp,client.port);
try {
DatagramSocket s = new DatagramSocket();
int count = 0 ;
while(true){
String msg = "消息"+count;
System.out.println("待发送消息:"+msg);
byte[] bytes = msg.getBytes();
//需要发送的数据
DatagramPacket packet = new DatagramPacket(bytes,bytes.length,address);
s.send(packet);
count++;
}
} catch (SocketException e) {
e.printStackTrace();
} catch (IOException ioException) {
ioException.printStackTrace();
}
}
}
服务端
1.创建InetSocketAddress对象封装本机Ip和端口
2.创建DatagramSocket,将本机Address对象传入
3.接收数据包DatagramPacket,并调用getData方法获取发送的数据
package udp.v1;
import java.io.IOException;
import java.net.DatagramPacket;
import java.net.DatagramSocket;
import java.net.InetSocketAddress;
import java.net.SocketException;
public class Server {
private String ip;
private int port ;
public Server(String ip, int port) {
this.ip = ip;
this.port = port;
}
public static void main(String[] args) {
Server server = new Server("127.0.0.1",1238);
InetSocketAddress address = new InetSocketAddress(server.ip,server.port);
try {
DatagramSocket s = new DatagramSocket(address);
while(true){
byte[] bytes = new byte[20];
DatagramPacket packet = new DatagramPacket(bytes,bytes.length);
s.receive(packet);
System.out.println("接收到的数据为:");
System.out.println(new String(packet.getData()));
}
} catch (SocketException e) {
e.printStackTrace();
} catch (IOException ioException) {
ioException.printStackTrace();
}
}
}
运行结果
客户端
服务器
帖子还没人回复快来抢沙发