百科知识

TCP和UDP大不同,一文读懂网络传输差异

TCP与UDP同属于TCP/IP协议簇的范畴

TCP/IP协议簇是一个包含多种协议的集合(例如:TCP、UDP、IP、FTP、HTTP、ICMP、SMTP等)。这些协议按照功能被划分为四个层次:链路层、网络层、传输层以及应用层。

UDP与TCP的差异性分析

2.1 TCP与UDP在连接模式上的区别

UDP与TCP在建立连接的方式上存在显著差异。UDP无需像TCP那样进行三次握手来建立连接,而TCP在通信开始前必须完成三次握手过程。

具体过程如下:

在发送端,应用层将数据交给传输层的UDP协议处理,UDP仅向数据添加UDP头部信息以标识其为UDP协议,随后将数据传递给网络层。在接收端,网络层将数据传递给传输层,UDP仅移除IP报文头部后将数据直接传递给应用层,无需进行任何数据拼接操作。2.2 TCP与UDP在可靠性方面的差异

UDP的无连接特性是其不可靠性的主要原因,由于无需建立连接,数据可以随时发送,这种模式显然缺乏可靠性保障。发送数据时,UDP并不关心接收方是否成功接收了数据。此外,网络环境可能时好时坏,但UDP缺乏拥塞控制机制,始终以恒定速率发送数据。即使网络状况不佳,也不会调整发送速率,这可能导致网络拥堵时出现丢包现象。然而,UDP的优点也十分突出,对于实时性要求较高的场景(如电话会议),UDP更为适用,因为即使有数据丢失(例如像素信息丢失),也不会对视频内容造成显著影响。从下图所示的动态图可以看出,UDP在发送数据时会将所有数据报文一次性发送给对方,而不关心数据是否安全完整地到达。

在TCP协议中,接收确认和重传机制确保了数据的可靠传输,每个信息都能保证到达。

相比之下,UDP采用尽力而为的传输方式,没有应答和重传机制,UDP仅负责将信息发送出去,并不确认对方是否接收。因此,UDP协议被认为是不可靠的。

2.3 TCP与UDP在数据传输模式上的区别

如何理解面向字节流和面向报文的概念呢?

TCP基于流的传输方式意味着它不将消息视为独立单元,而是将数据视为无保护边界的字节流(保护消息边界:指传输协议将数据作为独立消息在网络中传输,接收端一次只能接收一条独立消息)。

UDP面向报文,具有保护消息边界的特性,接收方一次只能接收一条独立的消息,因此UDP不存在粘包问题。

举个例子:假设有三个数据包,大小分别为2k、4k、6k,如果使用UDP发送,无论接收方的接收缓存有多大,都必须至少进行三次发送才能完成数据传输。而使用TCP协议发送时,只需确保接收方的接收缓存有12k的空间,就可以一次性将这三个数据包全部发送完毕。这会导致接收方在单次接收中获取到多条消息,从而引发粘包问题。

2.4 TCP与UDP在传输模式上的差异

UDP不仅支持一对一的传输模式,还支持一对多、多对多以及多对一等多种传输方式,即UDP提供了单播、多播和广播功能。TCP由于需要在通信前与目标主机进行三次握手连接,因此不支持一对多的传输模式。2.5 UDP与TCP在头部开销上的差异

UDP头部

UDP的头部非常简短,仅有8个字节。相比之下,TCP的头部至少需要20个字节,因此UDP的头部开销远小于TCP。

下图展示了UDP数据包的结构:头部数据由四个部分组成:源端口号、目的端口号、总长度(即UDP头部加上数据的长度)以及校验和。

TCP头部

TCP的头部至少需要20个字节。

2.6 TCP与UDP在数据传输问题上的差异

2.6.1 TCP粘包问题

TCP产生粘包问题的根本原因在于其面向连接的特性,TCP将所有消息视为字节流,因此无法区分不同的消息边界。

下图展示了TCP粘包的情况:第一次读取数据时,读取了5个字节,但第一个数据包有10个字节,因此只能分次读取。第二次读取时,读取了25个字节,将后续数据也一并读取,这就是典型的粘包现象。

解决粘包问题的最有效方法是明确消息边界,例如:

在包头中添加包体长度信息。包头是固定长度的4个字节,用于指示包体的长度。接收方首先读取包头以获取包体长度,然后根据该长度读取包体。2.6.2 UDP丢包问题

由于UDP缺乏应答和重传机制,数据包很容易在传输过程中丢失且无法察觉。

UDP丢包的主要原因包括:

接收端处理时间过长导致丢包:当接收端收到数据后,处理数据需要一定时间,处理完成后再次调用recv方法接收数据。在这两次调用之间,如果发来的数据包丢失,就会导致丢包。为解决此问题,可以将接收到的数据包存储在缓冲区中,并迅速返回继续recv。发送的数据包过大导致丢包:虽然send方法会自动将大包切割成小包进行发送,但过大的数据包仍然可能导致丢包。例如,超过50K的UDP数据包若不进行切割直接发送,也可能丢失。为避免这种情况,应将大包切割成小包后逐个发送。发送的数据包过大超过接收者缓存导致丢包:当数据包大小超过MTU(最大传输单元)的数倍时,多个大数据包可能超过接收者的缓冲区容量,导致丢包。为解决此问题,可以调整socket接收缓冲区的大小。例如,将接收缓冲区设置为64K可以解决此类问题。发送的数据包频率过高导致丢包:虽然每个数据包的大小都小于MTU,但如果发送频率过高(例如连续发送40个MTU大小的数据包且不进行任何延时),也可能导致丢包。总结