对于学过计算机网络的人来说,不得不提到TCP和UDP相关的概念以及知识。本节,我们简单介绍下TCP和UDP的特点。

传输控制协议TCP(Transmission Control Protocol)
- TCP是面向运输层的协议。简单来说,就是应用程序在使用TCP协议之前,必须先建立一个连接,在数据传输完毕后,需要释放已经建立的TCP连接;
- 每一个TCP连接都是点对点的;
- TCP提供可靠的服务。也就是说,通过TCP协议传输的数据是无差错,不丢失,不重复并按顺序到达的。通常,一些通用的上层协议若底层采用TCP协议传输,可以免交验(如modbus协议);
- TCP提供全双工通信。TCP连接的两端都设有发送和接收缓存,两端发送时可以将数据放入缓存中后去执行其他操作,也可以在适当的时候才到缓存中读取数据;
- 面向字节流。TCP和上层应用程序交互是一次一个数据块(大小不等),在TCP看来,这些只是一串无结构的字节流,TCP并不会去识别字节流的含义。在数据传输的过程中,TCP并不保证发送方应用程序发送的数据块和接收方应用程序接收的数据块完全一致,也就是说,在应用层把数据块交付给传输层时,可能会根据实际情况对数据块做进一步的整理。但是,从字节流的角度来看,发送方和接收方发送和接收到的字节流肯定是一致的。在接收方的应用程序需要对接收到字节流做进一步解析处理;

TCP面向流的概念
用户数据报协议UDP(User Datagram Protocol)
- 对比TCP协议,UDP主要有以下特点:
- UDP是无连接的。即数据的传输不需要提前建立连接;
- UDP是不可靠的。对比TCP传输,UDP不保证数据的可靠交付;
- UDP是面向报文的。简单来说,UDP接收到应用层传下来的报文后,添加首部后就向下传输给IP层,这个过程并不会将报文重新拆分或合并,而是保留这些报文的边界。UDP一次交付一个完整的报文,因此,在应用程序中,我们需要选择合适的报文大小。因为,若报文太长,交付到IP层会做分片处理,这会降低IP层的传输效率。反之,若报文太短,则使得IP数据报首部的相对长度太长,数据报有效数据比例较低,同样也降低了IP层的效率。

UDP-面向报文
除上述的几个特点外,UDP还有另外三个特点:
- UDP没有拥塞控制。网络出现的拥塞不会使源主机的发送速率降低。根据这个特点,UDP被广泛应用于IP电话,实时视频通话等);
- UDP支持一对一,一对多,多对一和多对多的交互通信。
- UDP的首部开销对比TCP要小。UDP首部开销8个字节,而TCP20个字节。
虽然某些实时应用需要使用没有拥塞控制的UDP,但是当有很多主机同时向网络发送高速率数据流时,网络就会很容易发生拥塞。
还要一些使用UDP的实时应用,需要对UDP的不可靠传输进行适当的改进,以减少数据的丢失。在这种情况下,在不影响应用实时性的前提下,可以增加一些可靠性的措施(如:前向纠错或重传已丢失的报文)
说完了这两者之间的特点,我们接下来就来对比下这两者之间的区别。
TCP和UDP两者之间最直观的区别,就体现在两者报文的首部格式上。
UDP的首部格式
用户数据报UDP主要由两个字段组成:数据字段和首部字段。这里我们介绍下它首部字段格式。UDP的首部字段主要由四个字段组成(共8个字节,每个字段两个字节)。各字段介绍如下:
- 源端口 源端口号,在需要对方回信时选用,不需要时可用全0;
- 目的端口 目的端口号,这在终点交付报文时必须要使用到;
- 长度 UDP用户数据报的长度,其最小值是8(仅首部);
- 检验和 检测UDP用户数据报在传输中是否有错。有错就丢失该数据报;
UDP数据报的格式如下图所示:

UDP数据报的格式
TCP的首部格式
对比UDP报文段的首部格式,TCP相对来说来复杂得多。
跟UDP一样,TCP报文段也同样分为首部和数据两部分。下面简单介绍下TCP报文段首部格式。
TCP报文段首部前20个字节是固定的,后面4N个字节是根据需要而增加的选项。因此,TCP报文段首部最小长度为20个字节。
首部固定部分各字段意义如下:
- 源端口和目的端口 各占两个字节,分别写入源端口号和目的端口号(同UDP类似);
- 序号 占4个字节。从第一篇我们知道,TCP是面向字节流的。在传输的字节流中,每一个字节都按顺序编号。而这个序号字段存储的正是本报文所发送的数据的第一个字节的序号。因此,我们也叫这个字段为“报文段序号”;
- 确认号 占4个字节,是期望收到对方下一个报文段的第一个数据字节的序号。举个例子:假如说B收到了A发送过来的一个报文段,其序号字段是501,数据长度是200个字节,也就是说B收到了A发送到序号为700为止的数据。因此,B希望收到A下一个数据序号为701,于是B在发送给A的确认报文段中吧确认号置为701。
- 数据偏移 占4位。这个字段指出了TCP报文段数据起始处距离TCP报文段起始处便宜了多少字节。这是因为TCP的首部是不固定的,数据偏移字段还是有必要的。
- 保留 预留的字段,占6位
- 紧急URG(URGent) 当URG==1时,表明紧急指针字段有效。它会告诉系统此报文段中有紧急数据,需要尽快传送(相当于高优先级的数据)。这通常用于数据传送过程中的紧急中断处理操作。
- 确认ACK(ACKnowlegment) 当ACK==1时,确认号才有效,反之则无效。在TCP连接建立后,必须把所有报文段的ACK置为1。
- 推送PSH(PuSH) 当两个应用程序在使用TCP进行数据交互时,有时候一方需要在键入一个命令后马上得到对方的响应,这个时候可以把PSH置为1,并立即创建一个报文段发送出去。接收方接收到此报文段后,会尽快推送交付给应用程序,给不需要等待缓存填满再向上交付。
- 复位RST(ReSet) 当RST == 1时,表明TCP连接出现错误,需要释放连接并重新建立运输连接。RST置1还可用来拒绝一个非法的报文段或拒接打开一个连接。该位也称为重建位或重置位。
- 同步位SYN(SYNchronization) 在连接建立时用来同步信号。当SYN==1而ACK==0时,表明这是一个连接请求报文段。若对方同意连接后,则应在响应报文段中使SYN==1和ACK==1。因此,SYN==1表明这是一个连接请求或连接接受报文。(这里涉及到TCP的连接过程相关知识,后面篇章再对这一块进行详解)
- 终止FIN(FINis) 用来释放一个连接,当FIN==1时,表明此报文段发送端的数据已发送完毕,并要求释放运输连接
- 窗口 占2个字节。窗口是指发送本报文段一端的接收窗口(注意!不是发送窗口);窗口字段明确指出了现在允许对方发送的数据量,这是因为接收方数据缓存是有限制的。窗口值处于动态变化中。
- 检验和 占2个字节。检验范围包括首部和数据这两部分。计算时,需要加上TCP报文段前面12字节的伪首部。
- 紧急指针 占2个字节。紧急指针仅在URG==1时才有意义。它指出了本报文段中紧急数据的字节数(紧急数据结束后就是普通数据)。紧急指针指出了紧急数据末尾在报文段中的位置。当所有紧急数据处理完后,TCP会告诉应用程序恢复正常操作。(注:窗口值为0也可以发送紧急数据)
- 选项 长度可变,最长可达40个字节。当没有使用选项时,TCP首部的长度是20个字节。(该字段这里就不再赘述了)

TCP数据报的格式
以上就是TCP和UDP报文首部字段的区别,其实差别还有体现在其他方面(比如TCP和UDP两者数据的传输过程,TCP的连接等),这里会在后续篇章叙述。今天就暂时先到这里吧。