TCP协议

报头格式

TCP头部规范
TCP报头长度为 20 - 60 字节,其中固定部分长度为 20 字节, 选项部分长度可变, 最多为 40 字节。

端口号

四个要素确定唯一一个连接:(源IP,源端口号)+(目的IP,目的端口号)
TCP的头部预留了两个16位作为端口号的位置,而IP地址由上一层IP协议负责传递

端口号占16位(两个字节),也就是端口的范围是 2^16 = 65535;
1024以下是系统保留,从1024-65535是用户的端口范围。

TCP的序号和确认号

32位序号 seq:Sequence number 缩写 seq,TCP 通信过程中某一个传输方向上的字节流的每个字节的序号,通过这个来确认发送的数据有序
32位确认号 ack:Acknowledge number 缩写 ack,TCP对上一次 seq 序号做出的确认号,用来响应 TCP 报文段,给收到的 TCP 报文段的序号seq加1。

头部长度

头部长度字段用来表示TCP报头总长度。
头部长度字段以 4 个字节为一个计算单元。

即该字段为 1 时表示 TCP 报头为 4 个字节长,为 2 时 TCP 报头为 8 个字节长…

头部长度字段使用 4 位(可表示 0-15 的数值)进行存储;而因为 TCP 报头的长度为 20 - 60 个字节,所以数值在 5 - 15之间。

该字段数值 5 表示 TCP 报头为 20 个字节,数值 15 表示 TCP 报头为 60 个字节。

保留

保留了6位给今后使用。

标志位(控制字段)

每个TCP段都有一个目的,这是借助于TCP标志位选项来确定的,允许发送方或接收方指定哪些标志应该被使用,以便段被另一端正确处理。
用的最广泛的标志是 SYN,ACK 和 FIN,用于建立连接,确认成功的段传输,最后终止连接。

标志 说明
SYN 同步标志位,用于建立会话连接,同步序列号;
SYN=1,ACK=0表示:这是一个连接请求报文段。若同意连接,则在响应报文段中使用SYN=1,ACK=1
因此,SYN=1表示这是一个连接请求,或连接接收报文,SYN这个标志位只有在TCP建立连接才会被置为1,握手完成后SYN标志位被置为0
ACK 确认标志位,对已接收的数据包进行确认;仅当ACK=1,确认号字段才有效
FIN 完成标志位,FIN=1表示我已经没有数据要发送了,即将关闭连接
PSH 推送标志位,RSH=1表示该数据包被对方接收后应立即交给上层应用,而不在缓冲区排队
RST 重置标志位,用于连接复位、拒绝错误和非法的数据包;RST=1表示出现严重差错,必须释放连接,然后重新建立连接。
URG 紧急标志位,表示数据包的紧急指针域有效,用来保证连接不被阻断,并督促中间设备尽快处理;URG=1需要配合紧急指针使用,由紧急指针指出在本报文端中的紧急数据的最后一个字节的编号。

紧急指针

16位,当紧急标志URG=1时该字段才有效,表示这个报文段中包含紧急数据。TCP 软件需要处理完紧急数据之后才能够恢复正常操作。

窗口大小

16位,表示接收方通知即将发送报文的发送方下一个报文中最多可以发送的字节数。必须维持的窗口大小(以字节为单位),用作控制发送端的缓存,以控制每次发送的流量(速率)。

该字段值是动态变化的。

可以理解为:发送方会根据窗口大小字段控制等待确认前最多给接收方发多少数据包

具体请看 滑动窗口协议 的内容

选项

选项有两类:单字节选项多字节选项。
单字节选项:

  • 选项结束
  • 无操作

多字节选项:

TCP 最大段长度(MSS)

TCP 协议对报文数据部分最大长度有一个规定,这个值称为最大段长度(maximum segment size, MSS)。

TCP 报文长度 = TCP 报头长度 + 数据部分长度(MSS)

MSS值的选择应该考虑以下几个方面的因素:

  • 协议开销:报文中数据长度在报文长度的占比,因报头长度相对固定,故 MSS 越大每个报文用来传输数据的比例越大,反之亦然。
  • IP分段:TCP 报文是要通过 IP 分组传输的,如果 MSS 值选择比较大,受到 IP 分组长度的限制,较长的报文段在 IP 层会被分段传输。分段会导致网络层的开销和传输出错的概率。
  • 发送和接收缓存区的限制:MSS 值的大小会直接影响到发送和接受缓冲区的大小与使用效率。
  • MSS的默认值:基于以上因素,确定默认的 MSS 值为 536 字节。编程人员可通过设置 SYN 报文中的最大段长度选项来协商。TCP 允许连接的双方选择不同的 MSS 值。

TCP 连接建立与释放

三次握手(建立TCP连接)

所谓的“三次握手”:为了对每次发送的数据量进行跟踪与协商,确保数据段的发送和接收同步,根据所接收到的数据量而确认数据发送、接收完毕后何时撤消联系,并建立虚连接。

为了建立连接TCP连接,通信双方必须从对方了解如下信息:

  1. 对方报文发送的开始序号(seq)。
  2. 对方发送数据的缓冲区大小(窗口大小)。
  3. 能被接受的最大报文长度MSS。
  4. 被支持的TCP选项。

第一次握手

建立连接时,客户端发送SYN包(seq=j)到服务器,并进入SYN_SENT状态,等待服务器确认;

syn:同步序列编号(synchronize sequence numbers)。

第二次握手

服务器收到syn包,必须确认客户端的SYN(ack=j+1),同时自己也发送一个建立连接的包(seq=k),即SYN+ACK包,此时服务器进入SYN_RECV状态。

ack: 确认号(acknowledge number)

第三次握手

客户端收到服务器的SYN+ACK包,向服务器发送确认包ACK(ack=k+1),此包发送完毕,客户端和服务器进入ESTABLISHED(TCP连接成功)状态,完成三次握手。

上述 ‘XXX包’表示将 XXX 标志位置 1,例如: SYN 包 即 SYN=1 的包。
注意:syn 和 ack 表示序号和确认号;SYN 和 ACK 表示同步标志位和确认标志位

四次挥手(释放TCP连接)

对于一个已经建立的连接,TCP使用四次挥手来释放连接(使用一个FIN=1的报文段)。
TCP关闭连接的步骤如下:

第一步

主机A的应用程序通知 TCP 数据已经发送完毕时,TCP 向 主机B发送一个FIN=1报文段。

FIN:完成标志位
主机A 发送 FIN=1 报文段后进入 FIN-WAIT-1 状态

第二步

主机B收到这个FIN=1报文段之后,先向主机A发送ACK=1报文段,同时通知自己相应的应用程序:对方要求关闭连接(先发送ACK的目的是为了防止在这段时间内,对方重传FIN报文段)。

主机A 收到 ACK=1报文段后进入 FIN-WAIT-2 状态
主机B 发送 ACK=1报文段后进入 CLOSE-WAIT 状态

第三步

主机B的应用程序告诉 TCP:我要彻底的关闭连接,TCP 向主机A发送一个FIN=1报文段。

主机B 发送 FIN=1报文段后进入 LAST-ACK状态

第四步

主机A 收到这个FIN=1报文段后,向** 主机B** 发送一个ACK=1表示连接彻底释放。

主机B 进入 CLOSE 状态

  • 主机B 发送ACK=1到发送 FIN=1之间(即第二步到第三步之间)TCP 连接还未断开,如果有需要可继续发送直至完毕。这种状态称为“半关闭”(half-close)状态。
  • 客户端和服务器端经过“四次挥手”后确认双方已经同意释放连接,客户端仍需要延迟 2 个 MSL(时间等待定时期)时间。设置等待延时机制的原因是:确保服务器在最后阶段发送给客户端的数据,以及客户端发送给服务器的最后一个ACK=1报文都能正确地被接收,防止因个别报文传输错误导致连接释放失败。

本博客所有文章除特别声明外,均采用 CC BY-SA 3.0协议 。转载请注明出处!