UDP协议
协议介绍
UDP (User Datagram Protocol)用户数据报协议。UDP是不可靠的、无连接的数据报服务。只是将应用层数据通过IP协议发送出去,而提供传输可靠性需要使用TCP协议。
UDP协议使用端口号区分发送端和接受端的进程,保留IP协议传输的原始特性,并没有定义不同于IP协议的传输行为。
RFC 768定义UDP首部格式如下:
![UDP](https://img-blog.csdn.net/20141102102605359?watermark/2/text/aHR0cDovL2Jsb2cuY3Nkbi5uZXQvc2hlbnhpbjg3MDQwOQ==/font/5a6L5L2T/fontsize/400/fill/I0JBQkFCMA==/dissolve/70/gravity/Center)
16位源端口、目的端口:标记应用进程。
16位UDP长度:UDP整体报文长度(包括UDP首部长度+UDP数据长度)。
16位UDP校验和:校验UDP报文的一致性。
校验和
UDP首部长度8字节,最小UDP报文为8字节,也就是没有UDP数据部分。
回想IP校验和只是校验IP首部,UDP校验和校验整个UDP报文,如此整个IP数据报文都得到校验,想必TCP校验和也是如此。但是校验和只是对反码求和,不能百分百保证数据的一致性,只是降低数据出错的可能性。
IP分片
UDP基于IP协议,必须遵从IP分片机制,由于链路层限制导致IP数据报必须进行分片。UDP应用层每次写操作产生一个IP数据报,如果UDP数据报长度小于MTU则远端可以正常发送出去,如果大于MTU长度则需要分片。
IP协议中定义MF(更多分片)标记,如果需要分片则除最后一个分片外应该设置MF标记,每个分片都共用一个IP数据报标识。
IP协议中定义DF(不需要分片)标记,如果打开该标记则IP数据报大于MTU必须丢弃,并且返回一个ICMP差错报文,此机制用于发现路径MTU。
当UDP应用程序需要传输一个1473字节的数据时导致IP分片发生。此时MTU=1500, 最大UDP数据应该是1472(1500-20-8)。
![IP分片](https://img-blog.csdn.net/20141102105402806?watermark/2/text/aHR0cDovL2Jsb2cuY3Nkbi5uZXQvc2hlbnhpbjg3MDQwOQ==/font/5a6L5L2T/fontsize/400/fill/I0JBQkFCMA==/dissolve/70/gravity/Center)
从上图我们发现UDP的首部字节只出现在第一个IP分片中,我举一个简单的例子印证这个现象。
我们在使用基于UDP的SIP协议进行抓包,SIP协议的端口通用5060,我们使用tcpdump指定端口进行协议抓包分析。比如下面这行命令:
tcpdump -s 0 -i any port 5060 -w xx.cap
使用wireshark进行SIP协议分析的时候经常出现包被截断了,无法看到完整的SIP消息。出现该现象的原因就是由于SIP消息过长导致IP分片,如果使用port 5060进行过滤只能抓到IP第一个分片,因为UDP的首部只出现在第一个分片,因此只能通过第一个分片才知道端口是5060的UDP报文。
UDP不可靠特性
1)应用程序使用类recv接口接受数据,需要传入一个接收缓存用于拷贝UDP数据报,如果发送端发送的数据报大于用户传入报文,剩余未被拷贝的数据定义行为不可靠,可能会被丢弃。
2)应用程序发送一系列报文,可能是由于中间路由吞吐量过小等原因丢弃,UDP无法感知并且控制发送的速率。
3)启用MTU发现机制,如果IP层对数据报标记DF,可能导致中间路由无法进行分片而丢弃数据报,UDP也无法感知。
4)UDP继承IP的不可靠性。
UDP协议思考
如此看来UDP没有做过多的事情,让用户尽可能的直截了当使用到IP协议的特性,并且封装出端口以区分不同的进程,帮助上层协议管理好操作系统分配的资源等等。
UDP继承了IP协议不可靠的特性,既然不可靠的协议如何使用才靠谱呢?我想一定是大家很关注这个问题,我谈谈几点对UDP协议的理解。
UDP有几类应用
1)使用UDP协议进行业务层面通讯,并且相信UDP协议可靠,上层业务会做一些异常处理。
2)使用UDP协议传输音视频等信息,相信UDP基本可靠,允许一定比例的丢包和乱序,使用冗余或者业务重传进行补充。
3)基于UDP协议实现的应用层协议,并且实现类似TCP的可靠性,比如SIP协议。
4)基于UDP协议实现的应用层协议,能够尽可能简单、实时,比如DNS等应用层协议。
5)某些特定使用场景需要可靠的传输协议,但是TCP协议过于复杂,希望基于UDP,让应用层协议实现可靠性的场景。
6)多播、广播等特性可以使用UDP协议,而不能使用TCP协议。
UDP虽然继承了IP不可靠的特性,也同时保留IP协议原始特性,实时、无连接。并且提供上层协议自身实现可靠性的机会。如果只有TCP一种选择,也就是上层协议失去选择的自由。
TCP协议
协议介绍
TCP (Transmission Control Protocol)传输控制协议。TCP提供一个面向连接的、可靠的字节流服务。
面向连接是指交互双方需要先建立连接、然后才可以进行通信,类似打电话过程,必须拨号接通后才能对话。
可靠的服务是指TCP使用重传、缓存数据报等机制提供一个可靠的通信服务。
字节流服务是有别于数据报服务,字节流传输没有严格的分界,比如两次分别写20字节,可以一次读出40字节,而不是像数据报协议需要读两次。
RFC 793定义TCP首部格式如下:
16位源端口、目的端口:用于区分进程的标识。
32为序号:用来标识TCP发送端发送的字节流。
32为确认序号:是接受端对收到的字节流确认的标识。
4为首部长度:单位是DWORD(4字节),最大长度60字节。类似IP协议的首部长度。
6个Bit标识:
URG: 标记是否是一个紧急指针。
ACK: 标识是否是TCP的确认报文。
PSH: 标识否立即推给应用层,目前SOCKET接口不支持设置该标记,完全由内核协议栈控制。
RST: TCP连接重置标记,连接被异常终止。
SYN: TCP发起建立连接的标记。
FIN:TCP发起终止连接的标记。
16位窗口大小:TCP滑动窗口的大小,单位字节。
16位校验和:校验TCP整个报文,类似UDP的校验和。
16为紧急指针:只有URG标识为1时有效,值是一个正的偏移量,和序号相加为字节流最后一个字节的标识。
选项:可选,包括MSS、Window Scale、SACK、时间戳等等,后续TCP详解章节进行分析。
TCP提供面向连接的可靠的服务,为了实现可靠性使得TCP协议栈实现非常复杂,因此不是几个章节能够介绍得清楚的,我会在后续的章节对TCP的特性进行详细分析,希望尽可能和实际应用联系起来,能够更好的理解TCP协议。
TCP与UDP的比较
TCP/UDP |
面向连接
| 传输模式 | 可靠性 | 系统资源 | 多播、广播 |
---|
TCP |
是
| 字节流 | 可靠 | 占用资源多 | 不支持 |
UDP |
否
| 数据报 | 不可靠 | 占用资源少 | 支持 |
小结
本章主要是对传输层的协议进行介绍,特别重点介绍UDP协议,以及对UDP协议的思考。初识TCP协议,以及TCP首部字段的简单介绍。对UDP和TCP两种传输方式进行比较,传输层和网络层对于上层软件开发工程师而言更为重要,因此是本系列的重点,特别是以TCP、IP协议为核心,会在后续章节重点阐述。
参考
《TCP/IP详解-协议》卷一 W.Richard Stevens
修订