TCP和UDP

TCP/IP模型

OSI模型七层从下到上分别是物理层、数据链路层、网络层、传输层、会话层、表示层和应用层。而在TCP/IP模型中,分别是数据链路层(物理层、数据链路层)、网络层、传输层和应用层(会话层、表示层、应用层)。TCP协议和UDP协议工作在传输层。

UDP

UDP协议全称是用户数据报协议,是一种无连接的协议。UDP不对数据包分组和组装,不能对数据包进行排序。当应用层将一个报文下传到UDP时,UDP不会对这个报文作任何额外处理,只会在报文头部添加UDP头标识然后原封不动传递给网络层。UDP不会对数据报文作任何额外处理,所以想要对数据进行分组、合并、排序组装要在应用层完成。同时UDP是不可靠的,UDP不要求接收方在收到数据需要应答,也不要求发送方重发数据包,这些都需要在应用层靠程序员实现。UDP还是有优点的,UDP支持单播、多播、广播,同时UDP头部占用资源小,不提供复杂功能也表示UDP传输效率高,只负责专心传输。UDP比较适合实时性要求严格但允许存在一些误差的场景,比如视频通话、语音通话等等。

TCP

TCP协议全称是传输控制协议。相比起UDP,TCP提供了更多功能,所以也更加复杂。需要注意的是,TCP只支持单播。

面向连接

TCP在传输数据时需要建立连接,包括建立连接与断开连接两个场景。在建立连接时需要有三次握手:
(1) A发起连接,发送一个SYM数据包到B,进入SYN-SEND状态
(2) B收到SYN包,发送一个SYN+ACK数据包给A,进入SYN-RECV状态
(3) A收到ACK包,发送一个ACK数据包给B,进入ESTABLISHED状态,A可以在这一步直接发送数据
(4) B收到ACK包,进入ESTABLISHED状态

在断开连接使需要有四次挥手:
(1) A发起断开连接请求,发送一个FIN数据包给B,进入FIN_WAIT_1状态
(2) B收到FIN包,返回一个ACK数据包给A,进入CLOSE_WAIT状态,此时断开了A到B的传输路径,但B依然可以发送数据给A
(3) 如果B没有数据要发送给A,B发送一个FIN数据包给A,进入LAST_ACK状态
(4) A收到FIN包,返回一个ACK数据包给B,进入TIME_WAIT状态,如果B没有再发送数据包过来,进入CLOSED状态
(5) B收到ACK包,进入CLOSED状态

可以看到,无论是建立连接还是断开连接,本质上是在以发送-确认的方式建立一条双向传输通道。建立连接之所以只需要发送三次数据包,是因为B将发送SYN和ACK合并在一起了。所以问为什么要三次握手,四次挥手,可以看作是问为什么需要确认机制,其中为了提升效率确认和发送数据是可以同时进行的。为什么需要确认呢,如果对方不返回确认,我们就无法得知对方有没有收到我们发送的数据,无法得知对方收到我们发送的哪部分数据,也就无法实现重新发送缺失数据的功能,也就无法实现可靠传输了。可以将面向连接看作是实现可靠传输的一部分。

面向字节流

UDP是面向报文的,即应用层给什么数据,UDP原封不动就发送,应用层的数据边界在UDP是依然存在的。而TCP是面向字节流的,应用层的数据到了TCP层并不会直接就发送,TCP存在发送缓存和接收缓存,只有当数据填满了发送缓存才会发送,也只有数据填满了接收缓存才会接收。这种缓存机制可以大大节省网络资源,但也造成一个问题,就是粘包问题。粘包问题是指应用层的数据边界不再像使用UDP时那么明确,在TCP缓存中可能存在着若干个数据报文,而一个数据报文也可能因为缓存被拆分成了若干份。要解决粘包问题,需要在应用层给数据边界作标记,然后在应用层实现数据复原。

可靠传输

TCP提供可靠传输服务,除了面向连接以外,TCP还提供了字节序号,数据重传,数据校验,流量控制,拥塞控制等功能。
(1) TCP在确认应答机制中提供了字节序号的标识,通信双方可以依据这个标识知道自己发送了多少数据,哪些数据已被对方接收,也可以通过这个标识告诉对方我收到了你哪些数据
(2) 基于TCP的确认应答机制以及字节序号的标识,通信双方可以及时发现哪个数据包丢失,从而发起数据重传
(3) TCP头标识中有校验位,用来校验数据的正确性与完整性
(4) TCP维护了两个窗口,分别是发送窗口和接收窗口。发送窗口指向发送发送缓存,在发送窗口之前的字节表示已发送并被成功接收,在发送窗口中的字节表示已发送但未被接收,在发送窗口之后的字节表示还未发送。当收到对方的确认ACK时,如果表示发送窗口第一个数据包被确认接收,则发送窗口右移;如果不是发送窗口第一个数据包被确认,则表示第一个数据包可能丢失了,继续等待,直到收到ACK或发起数据重传。接收窗口也是类似的过程,只是接收窗口指向对方发送的字节,可以将接收窗口大小发送给对方,当自己收到对方的接收窗口时,如果窗口比较小,说明对方可以接收的字节不多,此时可以缩小自己的发送窗口,从而达到流量控制的效果。需要注意,流量控制是控制通信双方的字节发送速度。数据的有序性也是靠这两个窗口实现
(5) TCP还提供了拥塞控制的功能,拥塞控制旨在监控网络的整体情况,调整合适的数据包发送速度,避免造成网络拥塞。与流量控制不同,拥塞控制的目的是避免网络堵塞,是一个宏观的调整过程。拥塞控制有慢启动、拥塞避免、快速重传等措施。慢启动是指在发送初始阶段,TCP先发送一个数据包,往后每收到一个ACK确认就增加一个数据包发送数量,在一个往返时间内,形成指数增加的发送趋势。拥塞避免是指慢启动达到一定程度后,TCP在一个往返时间内,发送的数据包个数只增加一,不再是慢启阶段的指数增加。当发送方收到三个拥有相同字节序号的ACK时,说明这个字节序号的数据包可能丢失,此时发起数据重传,不用再等到超时再重传,这是快速重传过程。当出现三次相同ACK时,将当前发送数据包个数削减一半并进入拥塞避免阶段。当发生超时时,即在规定时间没有收到对应数据包的ACK时,此时网络的拥塞情况可能较严重,重新开始慢启动阶段并重新发送丢失的数据包