计算机网络之我见-通俗理解计算机网络(六)

版权声明:本文为博主原创文章,未经博主允许不得转载。 https://blog.csdn.net/w1857518575/article/details/81667022

本篇讲解UDP协议

一、UDP协议的组成格式

# UDP协议格式比较简单,主要由协议头和协议体构成

# 协议头由源端口号、目的端口号、校验和、和包体长度字段组成

# UDP协议数据包由IP数据包承载,IP数据包头有两字节长度的包体字段的限制,包体最大长度为65535字节,所以理论上UDP数据包的长度最大为65535字节,但是各操作系统的实现不同,一般编程中使用的UDP Socket的允许的最大长度都会小于65535字节

二、UDP协议的不可靠性

1 不可靠性原因分析

# UDP数据报是由IP数据报承载的,IP数据报又是由链路层MAC帧承载的,MAC帧的最大长度是有限制的--MTU,一般的MTU都小于1500字节,所以过长的IP数据报在各节点间传输的时候会导致IP分片和重组,分片重组过程可能会导致数据丢失,如下几种情况:

路由器在等待接收一个分片的IP数据报的所有片的时候定时器超时,路由器并不会给源主机发送任何错误通告而是直接丢弃所有收到的数据报片,导致数据丢失

路由器一般都会有数据报转发缓冲区,如果路由器缓冲区队列满了,也会导致路由器直接丢弃所有发送的IP数据报,导致数据丢失

每个主机的协议栈实现中都会有UDP接收队列,当在指定端口接收UDP数据包的进程处理不过来的时候,UDP接收队列满了,也会丢弃后来的数据报

2 如何减少不可靠性

路由器缓冲区满这种情况我们可以采取的措施很少,UDP接收队列满导致丢失可以通过优化接收程序的代码实现来解决,我们可控的是尽量避免分片,如何避免分片?只要把我们发送的每个UDP包的长度限制在MTU之内就可以,然而到目的地之间的链路可能要经过好多跳,每跳线路的MTU我们又无法详细得到,如何设置数据报大小呢?一种方案是直接选择比较小的大小,比如512字节,但是这样传输效率可能会低一点;另一种方案是能够用一种方式探查到目的主机的线路中的最小MTU大小(一种可行算法是写个像上篇所讲的“路由跟踪”程序类似的链路MTU探查程序,基本原理是给IP数据包设置不分片标志,TTL递增的方式依次发送一个较大的数据包,链路间的路由器发现需要分片而不能分片的错误就会向源主机发送ICMP“需要分片”错误报告,然后我们减少数据包大小再发送,直到收不到ICMP错误报告为止)

三、UDP协议编程的注意事项

# 地址复用和端口复用

1 一般我们编程时创建一个UDP socket时可以指定绑定的IP和端口号,通常可以指定本机所有的IP(多网卡、回环地址、广播地址都算多IP)都通配绑定到指定端口,如192.168.0.2 、127.0.0.1都绑定到7777端口上的同一个Socket上,这样一个socket就可以接收本机的所有网卡收上来的端口为7777的UDP数据报

2 如果我们想创建多个socket,每个socket对应一个IP,但是都绑定到同一个端口上,这时就需要在创建socket的时候指定“地址复用”选项来创建(否则操作系统会提示创建失败),这样每个socket直接能接收它目的地址为它所绑定的IP的数据报

3 如果我们想建立IP和端口完全相同的多个UDP socket会怎样?答案是必须同时指定“地址复用”和“端口复用”选项,否者操作系统不会给创建的,收取数据的时候分两种情况:如果socket绑定的是广播地址,那么这几个socket都会收到相同的数据包的多个拷贝;如果socket绑定的不是广播地址,那么一个数据包只交给一个socket处理

额外:对于TCP socket来说,即使指定“地址复用和端口复用”选项也不能同时建立多个绑定IP和端口完全相同的socket!但是对于由于进程意外停止又重启进程的情况是可以绑定IP和端口完全相同的socket的,区别就是,此前停止的进程所关联的socket的状态是time-wait的等待关闭状态,不是激活的状态,不属于“同时存在的多个IP和端口完全相同的socket”的情况~

猜你喜欢

转载自blog.csdn.net/w1857518575/article/details/81667022