TCP 是面向连接的、可靠的流协议。流就相当于不间断的数据结构。
TCP 之所以能够提供可靠传输就在于 通过 校验和、序列号、确认应答、重发控制、连接管理以及窗口控制等机制去实现的。
下面会通过介绍 TCP 的首部格式进行展开,一一阐述 TCP 三次握手、四次挥手、滑动窗口、拥塞控制、流量控制和 UDP 协议。
三次握手
三次握手说明:
TCP 是基于全双工的可信传输协议,也就意味着数据可以同时在两个方向上传输。在建立三次握手的过程中也就是在检验双方发送和接收数据的能力是否具备。
第一次握手,这时候客户端知道自己具备了发送数据的能力,但还不知道服务端是否有接收和发送数据的能力。
第二次握手,当服务端接收到报文后,回复确认报文,此时服务端知道客户端具有发送报文的能力,并且知道自己具有接收和发送数据的能力,但还不知道客户端是否具有接收数据的能力。
第三次握手,当客户端收到服务端的确认报文后,知道服务端具备接收和发送数据的能力,因为服务端还不知道客户端具备接收数据的能力,所以还需要发送一个确认报文,告知服务端自己是具有接收能力的。
在网络状况比较复杂或比较差的情况下,发送方可能会连续发送多次建立连接的请求。如果 TCP 握手的次数只有两次,那么接收方只能选择接受请求或者拒绝连接请求,但并不清楚这次的请求是否是正常的请求。
如果是三次握手的话,客户端在接收到服务端 seq+1 的消息之后,通过对比,就可以判断当前连接是否是历史连接,如果是的话就会发送终止报文给服务端终止连接。如果不是历史连接就发送确认报文建立连接。
建立一个 TCP 连接需要三次握手,而终止一个 TCP 连接需要经过四次挥手,这是由于 TCP 的半关闭特性造成的,TCP 提供了连接的一端在结束它的发送后还能接收来自另一端数据的能力。
四次挥手
第一次挥手:客户端发送一个 FIN 报文(请求连接终止:FIN = 1),报文中会指定一个序列号 seq = u。并停止再发送数据,但依然能够接收数据,主动关闭 TCP 连接。此时客户端处于 FIN_WAIT-1 状态,等待服务端确认。
第二次挥手:服务端收到 FIN 之后,会发送一个 ACK 报文,且把客户端的序号值 +1 作为 ACK 报文的序列号值,表明已经收到客户端的报文了,此时服务端处于 CLOSE_WAIT 状态。客户端收到服务端的确认后,进入 FIN-WAIT-2 状态,等待服务端发出的连接释放报文段。
前两次挥手 既让服务端知道了客户端想释放连接,也让客户端知道了服务端了解了自己想要释放连接的请求。于是,可以确认关闭客户端到服务端方向上的连接的。
第三次挥手:如果服务端也想断开连接,会发送 FIN 报文,且指定一个序列号。此时服务端处于 LAST_ACK 状态,等待客户端的确认,并停止向客户端发送数据,但服务端仍能够接收从客户端传输过来的数据。
第四次挥手:客户端收到 FIN 之后,一样发送一个 ACK 报文作为应答(ack = w+1),且把服务端的序列值 +1 作为自己 ACK 报文的序号值(seq=u+1),此时客户端处于 TIME_WAIT 状态,并在这个状态等待 2MSL。服务端收到从客户端发出的 TCP 报文之后结束 LAST-ACK 阶段,进入 CLOSED 阶段。
客户端等待完 2MSL 之后,结束 TIME-WAIT 阶段,进入 CLOSED 阶段,由此完成四次挥手。
为什么客户端在 TIME-WAIT 阶段要等 2MSL?
为的是确认服务端是否收到客户端发出的 ACK 确认报文。
当客户端发出最后的 ACK 确认报文后,并不能确定服务端能够接收到,所以在发完之后,等待 2MSL,服务端在 1MSL 内没有收到客户端发出的 ACK 确认报文,就会再次向客户端发出 FIN 报文。
TCP 以 1 个段为单位,每发一个段就要进行一次确认应答的处理。这种传输方式有个缺点,包往返时间越长通信性能越低。
为了解决这个问题,引入了窗口这个概念。确认应答不再是以一个分段,而是以更大的单位进行确认,发送端发了一个段后不需要一直等待确认应答,而是能够继续发送。
窗口大小就是指无需等待确认应答而可以继续发送数据的最大值,窗口大小分为四个段。
如上图所示,白色部分就是窗口,窗口内的数据即便没有收到确认应答也可以发送出去。
滑动窗口以外的部分包括尚未发送的数据和已经确认对端收到的数据。收到确认应答后,会将窗口滑动到确认应答中的
序列号的位置。这样就可以顺序的将多个段同时发送提高通信性能。这种机制就是窗口滑动机制。
窗口滑动机制下重发处理
在使用窗口控制时,可能会遇到段丢失。在没有使用窗口控制,没有收到确认应答的数据会被重发,使用了窗口滑动,默写应答即使丢失也不需要进行重发。
结合下图所示,当某段报文丢失后,发送端会一直收到序号 1001 的确认应答,这个确认应答就像在提醒发送端"我想接收的是从 1001 开始的数据"。
出现报文丢失的情况下,同一个序号的确认应答会重复发送。当发送端连续三次收到同一个应答,就会将所对应的数据进行重发,这种重发机制叫做高速重发机制。
TCP 提供了一种机制可以让发送端根据接收端的实际接收能力控制发送的数据量。
接收端主机向发送端主机通知自己可以接收的数据大小,发送端就会发送不超过这个限度的数据。其实这个大小就是窗口大小,窗口大小的值是由接收端决定的。
因为计算机是个共享的环境,也有可能会因为其他主机之间的通信造成网络拥堵。在网络出现拥堵时,突然发送一个较大量的数据可能会导致网络瘫痪,如果在通信一开始就发送大量数据,也会引发一些问题。
TCP 为了防止这个问题,会利用一个慢启动的算法,对发送数据量进行控制。
为了调节发送的量,定义了一个叫做拥塞窗口的概念。
在慢启动的时候,将拥塞窗口大小设置为 1 个数据段(1 MSS)大小。之后每收到一个确认应答,就将窗口值加 1。
在发送数据包的时候,将拥塞窗口大小与接收端主机通知的窗口大小做对比,按它们中较小的值,发送比其还要小的数据量。
UDP是面向无连接的协议, 是一个不具有可靠性的数据报协议。不确保消息一定会到达。
UDP 主要用于对高速传输和实时性有较高要求的通信或广播通信。例如打电话,如果使用 TCP ,数据在传输过程如果有丢失就会被重发,但这样就无法流畅的传输人的声音,会造成声音大幅度延迟。
UDP 适用范围: