UDP是面向无连接的通讯协议,由于通讯不需要连接,所以可以实现广播发送。UDP通讯时不需要接收方确认,属于不可靠的传输,可能会出现丢包现象,实际应用中要求程序员编程验证。
UDP适用于DNS、视频音频等多媒体通信、广播通信(广播、多播)。例如我们常用的,就是一个以UDP为主,TCP为辅的通讯协议。
UDP报文格式如下:

UDP首部有8个字节,由4个字段构成,每个字段都是两个字节,
源端口:数据发送方的端口号.
目的端口:数据接收方的端口号。
长度:UDP数据报的整个长度(包括首部和数据),其最小值为8(只有首部)。
校验和:检测UDP数据报在传输中是否有错,有错则丢弃。
可以使用nc发送UDP数据包:echo hello | nc -uv 127.0.0.1 9999。
用tcpdump抓取到的数据包如下(注意先运行tcpdump,然后再执行nc命令):
说明:
源端口:0xb262,十进制的45666。
目的端口:0x270f,十进制的9999。
长度:0x000e,14个字节的报文长度。
校验和:0xfe21。
bio之单播
单播就是一对一通信。
服务器端代码如下:
讯享网
客户端代码如下:
客户端和服务端的代码几乎一致,只不过接收和发送数据的顺序不一致,receive和sendjava为udp提供的基础套接字都欧式阻塞方法。
bio之广播
广播:同一网段所有主机都能接收,前提是端口要开启监听。
只需要将单播的例子中客户端发送数据的IP修改为255.255.255.255即可,具体修改如下:
DatagramPacket datagramPacket = new DatagramPacket(req, req.length, new InetSocketAddress("255.255.255.255", 9999));
bio之多播(组播)

多播数据报套接字类用于发送和接收IP多播包。MulticastSocket是一种DatagramSocket,它具有加入Internet上其他多播主机的“组”的附加功能。
多播组通过D类IP地址和标准UDP端口号指定。D类IP地址在224.0.0.0和239.255.255.255的范围内。地址224.0.0.0被保留,不应使用。
可以通过首先使用所需端口创建MulticastSocket,然后调用joinGroup(InetAddress groupAddr)方法来加入多播组。
服务器端代码如下:
讯享网
客户端代码如下:
NIO实现单播
服务器端代码如下:
客户端代码如下:
Netty实现单播
服务器端代码如下:
客户端代码如下:
Netty实现广播
只需要将netty实现的单播的客户端代码做如下修改:
1.增加option:
.option(ChannelOption.SO_BROADCAST, true)
2.将IP地址修改为广播地址255.255.255.255:
channel.writeAndFlush(new DatagramPacket(Unpooled.copiedBuffer("hello server", CharsetUtil.UTF_8), new InetSocketAddress("255.255.255.255", 8899)));
底层实现
recvfrom负责接收UDP数据,其函数声明如下:
ssize_t recvfrom(int sockfd, void *buf, size_t len, int flags, struct sockaddr *src_addr, socklen_t *addrlen);
sendto负责发送UDP数据,其函数声明如下:
ssize_t sendto(int sockfd, const void *buf, size_t len, int flags, const struct sockaddr *dest_addr, socklen_t addrlen);
下面通过对bio之单播的例子所产生的系统调用进行跟踪:
启动服务器端服务Server:
# strace -ff -o out java Server
然后使用nc命令充当客户端进行连接:echo hello | nc -uv 127.0.0.1 9999。
产生的系统调用中关键信息如下:
可见发送和接收数据确实使用了上面的系统调用,另外上面的系统调用中并没有listen函数,不需要监听端口,再次验证UDP是面向无连接的。
版权声明:本文内容由互联网用户自发贡献,该文观点仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容,请联系我们,一经查实,本站将立刻删除。
如需转载请保留出处:https://51itzy.com/kjqy/1050.html