[关闭]
@Scrazy 2017-04-10T05:01:50.000000Z 字数 2995 阅读 1268

TCP

TCP


TCP 头部图。

TCP头部

  • Source Port和Destination Port:分别占用16位,表示源端口号和目的端口号;用于区别主机中的不同进程,而IP地址是用来区分不同的主机的,源端口号和目的端口号配合上IP首部中的源IP地址和目的IP地址就能唯一的确定一个TCP连接;
  • Sequence Number:用来标识从TCP发端向TCP收端发送的数据字节流,它表示在这个报文段中的的第一个数据字节在数据流中的序号;主要用来解决网络报乱序的问题;
  • Acknowledgment Number:32位确认序列号包含发送确认的一端所期望收到的下一个序号,因此,确认序号应当是上次已成功收到数据字节序号加1。不过,只有当标志位中的ACK标志(下面介绍)为1时该确认序列号的字段才有效。主要用来解决不丢包的问题;
  • Offset:给出首部中32 bit字的数目,需要这个值是因为任选字段的长度是可变的。这个字段占4bit(最多能表示15个32bit的的字,即4*15=60个字节的首部长度),因此TCP最多有60字节的首部。然而,没有任选字段,正常的长度是20字节;
  • TCP Flags:TCP首部中有6个标志比特,它们中的多个可同时被设置为1,主要是用于操控TCP的状态机的,依次为URG,ACK,PSH,RST,SYN,FIN。每个标志位的意思如下:
    • URG:此标志表示TCP包的紧急指针域(后面马上就要说到)有效,用来保证TCP连接不被中断,并且督促中间层设备要尽快处理这些数据;
    • ACK:此标志表示应答域有效,就是说前面所说的TCP应答号将会包含在TCP数据包中;有两个取值:0和1,为1的时候表示应答域有效,反之为0;
    • PSH:这个标志位表示Push操作。所谓Push操作就是指在数据包到达接收端以后,立即传送给应用程序,而不是在缓冲区中排队;
    • RST:这个标志表示连接复位请求。用来复位那些产生错误的连接,也被用来拒绝错误和非法的数据包;
    • SYN:表示同步序号,用来建立连接。SYN标志位和ACK标志位搭配使用,当连接请求的时候,SYN=1,ACK=0;连接被响应的时候,SYN=1,ACK=1;这个标志的数据包经常被用来进行端口扫描。扫描者发送一个只有SYN的数据包,如果对方主机响应了一个数据包回来 ,就表明这台主机存在这个端口;但是由于这种扫描方式只是进行TCP三次握手的第一次握手,因此这种扫描的成功表示被扫描的机器不很安全,一台安全的主机将会强制要求一个连接严格的进行TCP的三次握手;
    • FIN: 表示发送端已经达到数据末尾,也就是说双方的数据传送完成,没有数据可以传送了,发送FIN标志位的TCP数据包后,连接将被断开。这个标志的数据包也经常被用于进行端口扫描。
  • Window:窗口大小,也就是有名的滑动窗口,用来进行流量控制

相对于 UDP 来说,TCP 的信息传输是可靠的。为啥可靠,慢慢道来:

TCP 发起连接

三次握手

三次握手图
1. 客户端发送一个 TCP 分组,其中有个特殊的 SYN 标记,置为 1(表示要求联机),并随机生成一个 seq=J。发送给 服务端,其进入 SYN_SEND 状态。
2. 服务端对 SYN 进行确认,设置 Ack_num =J+1,同时,自己也要发送 SYN=1 ACK=1和 seq=K。将它们放进一个报文段(SYN + ACK_num)中,一并发送给客户端。进入 SYN_RECV 状态。
3. 客户端收到(SYN+ACK)报文段,确认 ACK_num=J+1。然后,再回复一个报文段 ACK_num=K+1,ACK=1于是,经服务端确认,二者进入 ESTABLISHED 状态。

TCP 断开连接

四次挥手

四次挥手
TCP 断开连接可以是客户端或服务端发起的。
下面用客户端发起断连来说明:
1. 客户端发送一个 FIN=1, seq=u 关闭 C/S之间的数据传输。进入 FIN_WAIT_1状态。
2. 服务端收到 FIN,返回一个ACK_num 给客户端,其值为 u+1, 并进入 FIN_WAIT_2 状态。
3. 服务端发送 FIN=1, seq=v, 关闭S/C之间的数据传输,进入 LAST_ACK 状态。
4. 客户端收到 FIN 进入 TIME_WAIT状态, 并发送 ACK_num=v+1 到服务端,客户端等待 2MSL 后,确认服务端收到 ACK 回复,二者进入 Closed 状态

TCP 细节

1. 握手时延

TCP 握手时延
对于片段较小的 HTTP 事务,会浪费较多的 网络资源。

2. 延迟确认和累积 ACK 回复

由于网络传输的不可靠性,TCP实现了自身的确认机制来确保数据的成功传输。接收方每成功收到一个数据片段,都会发送一个 ACK 回复来告知发送方。但这样太没有效率,于是,TCP 通过一个 ACK 回复来知会连续多个片段的成功接收(累积 ACK)。 而且,由于 ACK 回复很小,可以让发往同方向的输出数据进行“捎带”。延迟确认 就是为了寻找能够捎带 ACK 回复的输出数据。

3. TCP 滑窗

阻塞窗口

发送方滑窗可以分为下面两个部分。提议窗口(offered window)等于整个滑窗的大小。
接收窗口
接收方滑窗可分为三个部分
发送方
如图所示:
接收方的滑窗相对于发送方的滑窗多了一个“Received; ACKed; Not Sent to Proc”的部分。如果进程正忙于做别的事情,那么这些文本流即使已经正确接收,还是需要暂时占用接收缓存。当出现上述占用时,滑窗的可用部分,也就是图中的广播窗口(advertised window)就会缩水。这意味着接收方的处理能力下降。如果这个时候发送方依然按照之前的速率发送数据给接收方,接收方将无力接收这些数据。

流量控制

TCP 可以根据情况调节窗口的大小,来实现流量控制。即把接收方的窗口大小知会发送方,以此来指导发送方修改窗口的大小。

白痴窗口综合症

解决办法:
1. 接收方窗口必须达到一定尺寸,否则等待
2. 除了特殊情况(最小化延迟的 HTTP 应用 eg:命令行互动),发送方的数据片段也必须达到一定尺寸,否则等待

4. TCP 慢启动(slow start)和拥塞控制(congestion control)

为了防止一下向网络中注入太多的数据造成堵塞,TCP 采用慢启动的方式。
TCP协议通过控制滑窗大小(cwnd)来控制发送速率。
阻塞窗口总是处于慢启动和堵塞避免两个状态中的一个。

  1. 阻塞窗口从慢启动开始,以一个较低的速率传输,随着传输的成功,每次增大传输的速率(倍增)。
  2. 当阻塞窗口达到一定阀值时进入堵塞避免状态,发送速率缓慢增长,如果,此时有数据片段丢失,慢启动重新开始,阀值缩小为阻塞窗口大小的一半。

5. TCP 重新发送

TCP 是一个可靠的协议,它可以对丢失的片段重新发送。只要不成功,就一直重发。

超时重发(RTO,retransmission timeout)

数据的发送的 ACK 回复所花费的时间即为发送方应该等待的时间。这段时间被称为 RTT (round trip time)。但实际上,TCP 所用的是 SRTT (sampling round trip time)。数据发送后开始计时,如果超时就重新发送。

快速重发

有时, TCP 也会打断计时,立即重发,这就是快速重新发送。IP包是乱序的,当后一个(6)片段已经收到后,前一个(5)还没收到的话,接收方就向发送方回复ACK 序号为(5), 当发送方收到 3 个 ACK 序号为 5 的回复时,无论此时,片段 5 的计时器有没有超时,发送方都会打断计时器,立即重新发送片段 5。

参考:
1. 协议森林 -- by Vamei
2. HTTP 权威指南
3. 简析TCP的三次握手与四次分手

添加新批注
在作者公开此批注前,只有你和作者可见。
回复批注