UDP(User Datagram Protocol,用户数据报协议)是一种无连接的、不可靠的传输协议,它直接在网络层之上提供数据传输服务.
本文章将分成几部分去介绍它.
目录
一.UDP协议端格式
UDP 协议的格式相对简单,主要由以下几个部分组成:
- 源端口号(Source Port):占用2个字节,表示发送方端口号。
- 目标端口号(Destination Port):占用2个字节,表示接收方端口号。
- 长度(Length):占用2个字节,表示UDP数据报文的长度,包括头部和数据部分。
- 检验和(Checksum):占用2个字节,用于检测UDP数据报在传输过程中是否有错误。
- 数据(Data):占用0个或多个字节,实际传输的数据部分。
二.UDP的特点
UDP(User Datagram Protocol,用户数据报协议)具有以下几个主要特点:
无连接性:UDP 是一种无连接的传输协议,通信双方在传输数据之前不需要建立连接。这意味着每个 UDP 数据报文都是独立的,发送方不会跟踪接收方的状态。
不可靠性:UDP 不提供可靠性保证,它不会对数据传输进行确认或重传。因此,UDP 数据报文在传输过程中可能会丢失、重复或乱序。虽然 UDP 协议本身不提供这些功能,但是应用层可以通过自身的逻辑来实现数据传输的可靠性。
简单快速:相对于 TCP,UDP 协议的头部开销较小,没有 TCP 那样的连接管理、拥塞控制和重传机制。因此,UDP 的处理速度较快,适用于对实时性要求较高的应用,如视频流、音频流等。
面向数据报:应用层交给UDP多长的报文,UDP原样发送,既不会拆分,也不会合并;
缓冲区:UDP只有接收缓冲区,没有发送缓冲区,UDP的socket既能读,也能写这个概念叫做全双工.
大小受限:UDP协议首部中有一个16位的最大长度。也就是说一个UDP能传输的数据最大长度是64K(包含UDP首部)。
三.基于UDP的应用层协议
以下是一些常见的基于UDP的应用层协议:
DNS(Domain Name System,域名系统):DNS 使用UDP协议进行域名解析,将域名转换为对应的IP地址。DNS使用UDP而不是TCP主要是因为UDP的简单性和快速性更适合域名解析这种频繁且对响应时间要求较高的应用场景。
DHCP(Dynamic Host Configuration Protocol,动态主机配置协议):DHCP用于自动分配IP地址、子网掩码、网关等网络配置信息。DHCP在客户端与服务器之间进行通信,通常使用UDP作为传输协议,因为它的简单性和快速性更适合网络启动过程中的配置需求。
TFTP(Trivial File Transfer Protocol,简单文件传输协议):TFTP是一种简单的文件传输协议,用于在网络中传输文件。它使用UDP作为传输层协议,相对于FTP(File Transfer Protocol),TFTP更轻量级,适用于一些对可靠性要求不高但需要快速传输文件的场景。
SNMP(Simple Network Management Protocol,简单网络管理协议):SNMP用于网络设备之间的管理和监控,通过查询和设置网络设备的参数来实现网络管理。SNMP通常使用UDP进行数据传输,因为它的简单性和快速性更适合频繁的管理操作。
NTP(Network Time Protocol,网络时间协议):NTP用于同步网络中各个设备的时间,保持时间的一致性。NTP使用UDP进行时间信息的传输,因为它的实时性要求较高,而UDP的快速性更符合这一需求。
RTP(Real-time Transport Protocol,实时传输协议):RTP用于在互联网上传输实时音频和视频数据。它通常使用UDP进行数据传输,因为UDP的简单性和快速性更适合实时数据传输的需求,而TCP的可靠性保证机制可能会引入较大的延迟。
四.通过UDP传输数据(JAVA)
我们先了解JAVA中有关UDP的几个类
1.DatagramSocket类
DatagramSocket 是UDP Socket,用于发送和接收UDP数据报。以下是它的常见方法:
构造方法:
DatagramSocket()
: 创建一个未绑定到任何本地地址和端口号的DatagramSocket对象。DatagramSocket(int port)
: 创建一个绑定到指定端口号的DatagramSocket对象。
发送数据报:
void send(DatagramPacket packet)
: 发送指定的数据报。
接收数据报:
void receive(DatagramPacket packet)
: 接收数据报。
关闭:
void close()
: 关闭DatagramSocket对象。
获取和设置相关属性:
int getPort()
: 获取DatagramSocket绑定的端口号。void connect(InetAddress address, int port)
: 将DatagramSocket连接到指定的远程地址和端口。void disconnect()
: 断开DatagramSocket与远程地址的连接。boolean isClosed()
: 判断DatagramSocket是否已关闭。boolean isConnected()
: 判断DatagramSocket是否已连接到远程地址。
超时设置:
void setSoTimeout(int timeout)
: 设置接收超时时间,单位为毫秒。int getSoTimeout()
: 获取接收超时时间。
2.DatagramPacket类
DatagramPacket类用于表示数据报(Datagram),它包含了数据以及数据的目标地址和端口号等信息。以下是DatagramPacket类的常见方法:
构造方法:
DatagramPacket(byte[] buf, int length)
: 创建一个用于发送或接收数据的DatagramPacket对象,指定数据缓冲区和数据长度。DatagramPacket(byte[] buf, int length, InetAddress address, int port)
: 创建一个用于发送或接收数据的DatagramPacket对象,同时指定目标地址和端口号。
获取和设置相关属性:
byte[] getData()
: 获取数据缓冲区。int getLength()
: 获取数据长度。void setData(byte[] buf)
: 设置数据缓冲区。void setLength(int length)
: 设置数据长度。InetAddress getAddress()
: 获取目标地址。int getPort()
: 获取目标端口号。void setAddress(InetAddress address)
: 设置目标地址。void setPort(int port)
: 设置目标端口号。
发送和接收数据报:
- 无特定方法,通常通过DatagramSocket类的
send()
和receive()
方法来发送和接收DatagramPacket对象。
- 无特定方法,通常通过DatagramSocket类的
3.InetSocketAddress类
InetSocketAddress类是Java中表示IP地址和端口号的一个组合的类。它继承自SocketAddress
类,并提供了一些用于操作IP地址和端口号的方法。
InetSocketAddress ( SocketAddress 的子类 )构造方法:
1.InetSocketAddress(InetAddress addr, int port) 创建一个Socket地址,包含IP地址和端口号
了解以上三个类后,我们就可以正式开始编程了
4.编写UDP服务端
代码如下:
public class UdpServer {
//我们要绑定的端口
private static int PORT=8888;
public static void main(String[] args) throws IOException {
//创造服务端DatagramSocket,指定端口,可以发送和接受UDP报
DatagramSocket socket=new DatagramSocket(PORT);
//有了服务端就可以不停的接收数据了
while (true){
//创造数据报用于接收数据
byte[] bytes=new byte[1024];
DatagramPacket packet=new DatagramPacket(bytes, bytes.length);
//数据报packet创建好了后就可以等待接收了
//接收到的数据报放到packet中
socket.receive(packet);
//打印数据的信息
System.out.printf("客户端IP:%s%n",packet.getAddress().getHostAddress());
System.out.printf("客户端端口号:%s%n", packet.getPort());
System.out.printf("客户端发送的原生数据为:%s%n", Arrays.toString(packet.getData()));
System.out.printf("客户端发送的文本数据为:%s%n", new String(packet.getData()));
}
}
}
5.编写UDP客户端
代码如下
public class UdpClient {
//服务端socket地址,包含域名或IP,及端口号
private static final SocketAddress ADDRESS=new InetSocketAddress("localhost",8888);
public static void main(String[] args) throws IOException {
//创建客户端DatagramSocket,没指定端口将开启随机端口,可以发送及接收UDP数据报
DatagramSocket socket=new DatagramSocket();
//准备要发送的数据的内容
byte[] bytes="Hello world!".getBytes();
//打包成Udp数据包
DatagramPacket packet=new DatagramPacket(bytes, bytes.length,ADDRESS);
//发送数据
socket.send(packet);
}
}
接着我们先开启服务端等待接收数据,再开启客服端发送数据,就得到如下结果:
客户端IP:127.0.0.1
客户端端口号:52775
客户端发送的原生数据为:[72, 101, 108, 108, 111, 32, 119, 111, 114, 108, 100, 33, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0......]
客户端发送的文本数据为:Hello world!........
这样我们就成功的用UDP实现发送和接收数据了
到这里对UDP的介绍就结束了~~
读者读完后也建议自己实际编写一遍来巩固一下