TCP报文段格式
- 源端口:占16比特,写入源端口号,用来标识发送该TCP报文段的应用进程
- 目的端口:占16比特,写入目的端口号,用来标识接收该TCP报文段的应用进程
- 序号:占32比特,取值范围$[0, 2^{32}-1]$,序号增加到最后一个后,下一个序号就又回到0。TCP报文段的数据载荷中的每个字节都有序号,首部中的序号是TCP报文段数据载荷的第一个字节的序号
- 确认号:占32比特,取值范围$[0, 2^{32}-1]$,确认号增加到最后一个后,下一个确认号就又回到0。指出期望收到对方下一个TCP报文段的数据载荷的第一个字节的序号,同时也是对之前收到的所有数据的确认
- 确认标志位
ACK
:取值为1时确认号字段才有效,取值为0时确认号字段无效。TCP规定,在连接建立后所有传送的TCP报文段都必须把ACK置1 - 同步标志位
SYN
:在TCP连接建立时用来同步序号 - 终止标志位
FIN
:用来释放TCP连接 - 复位标志位
RST
:用来复位TCP连接,当RST=1
时,表明TCP连接出现了异常,必须释放连接,然后再建立连接。RST
置1还用来拒绝一个非法的报文段或拒绝一个TCP连接 - 推送标志位
PSH
:接收方的TCP收到该标志位为1的报文段会尽快上交应用程序,而不必等到接收缓存都填满再向上交付 - 紧急标志位
URG
:取值为1时紧急指针字段有效 - 紧急指针:占16比特,以字节为单位,用来指明紧急数据的长度。当发送方有紧急数据时,可将紧急数据插队到发送缓存的最前面,并立刻封装成TCP报文段进行发送。紧急指针会指出本报文段数据载荷部分包含多长的紧急数据,紧急数据之后是普通数据。接收方收到紧急指针为1的报文段,会按照紧急指针字段的值,从数据载荷部分取出紧急数据,并直接上交应用进程,而不必在接收缓存中排队
- 首部长度:占4比特,并以4字节为单位。用来指出TCP报文段的首部长度,首部固定长度20字节,因此首部长度字段的最小值为$(0101)_2$,首部最大长度为60字节,因此首部长度字段的最大值为$(1111)_2$
- 保留:占6比特,保留为今后使用,目前应置为0
- 窗口:占16比特,以字节为单位。指出发送本报文段的一方的接收窗口,窗口值作为接收方让发送方设置其发送窗口的依据,这是以接收方的接收能力来控制发送方的发送能力,称为流量控制
- 校验和:占16比特,检查范围包括TCP报文段的首部和数据载荷两部分
TCP报文段除了20字节的固定部分,还有最大40字节的选项部分,目前有以下选项:
- 最大报文段长度MSS:TCP报文段数据载荷部分的最大长度
- 窗口扩大选项
- 时间戳选项
- 选择确认选项
填充字段:由于选项的长度可变,因此使用填充来确保报文段首部能被4整除,因为首部长度字段是以4字节为单位的
TCP三次握手
最初,客户端和服务器端的TCP进程都处于关闭状态,一开始,TCP服务器进程首先创建传输控制块,之后进入监听状态,等待客户端的连接请求
TCP客户端进程也是首先创建传输控制块,然后在打算建立TCP连接时,向服务器进程发送连接请求报文段,并进入同步已发送状态SYN_SENT
,连接请求报文段首部中的SYN被设置为1,序号字段seq设置一个初始值x,作为TCP客户端进程所选择的初始序号
TCP规定SYN被设置为1的报文段不能携带数据,但要消耗掉一个序号
服务器进程收到连接请求报文段后,就向客户进程发送TCP连接请求的确认报文段,并进入同步已接收状态SYN_RCVD
,该报文段首部中的同步位SYN
和确认位ACK
都设置为1,序号字段seq
设置为初始值y,作为TCP服务器进程所选择的初始序号,确认号字段ack
设置为x+1,这个报文段也不能携带数据
TCP客户进程收到确认报文段后,还要回一个普通的确认报文段,并进入连接已建立状态ESTABLISHED
,将确认位ACK
设置为1,序号字段seq
设置为x+1,这是因为客户进程发送的第一个报文段的序号为x,并且不携带数据,因此第二个报文段的序号为x+1,确认字段ack
被设置为y+1,这是对服务器进程所选择的初始序号的确认,服务器进程收到该报文后也进入连接已建立状态ESTABLISHED
,现在,双方都进入了连接已建立状态,可以进行数据传输了
采用“三次握手”而不是“两次握手”建立TCP连接,是为了防止已失效的连接请求报文段突然又传到了服务器,因而导致错误
TCP四次挥手
TCP客户进程会发送连接释放报文段,并进入终止等待1FIN_WAIT_1
状态,该报文段首部中的终止位FIN
和确认位ACK
被设置为1,表明这是一个TCP连接释放报文段,同时也对之前收到的报文段进行确认,序号seq
字段设置为u,等于客户进程之前已发送过的数据的最后一个字节的序号加1,确认号ack
设置为v
TCP服务器进程收到连接释放报文段后,会发送一个普通的确认报文段,并进入关闭等待状态CLOSE_WAIT
,ACK
设置为1,序号seq
设置为v,确认号ack
设置为u+1,这是对客户端发送的连接释放报文段的确认。此时,客户端到服务端的方向的连接就释放了,这时的TCP连接处于半关闭状态,也就是客户端没有数据要发送了,但服务器如果还有数据要发送,客户端依然要接收
客户端收到确认报文段就进入终止等待2FIN_WAIT_2
状态
如果服务器也没有数据要发送了,就发送连接释放报文段并进入最后确认状态LAST_ACK
,该报文段首部中的终止位FIN
和确认位ACK
都设置为1,假定序号seq
字段的值为w,确认号ack
的值为u+1,这是对之前收到的连接释放报文段的重复确认
客户端收到连接释放报文段后,发送普通的确认报文段,然后进入时间等待状态TIME_WAIT
,该报文段首部中的确认位ACK
设置为1,序号seq
的值为u+1,确认号ack
的值为w+1
服务器收到确认报文段后就进入关闭状态
而客户端要进过2MSL
(Maximum Segment Lifetime)后才能进入关闭状态
如果客户端发送完确认报文段后就直接进入关闭状态,该报文段可能在传输过程中丢失了,这会导致服务器端的连接释放报文段的超时重传,但此时客户端已经处于关闭状态,因此不理会该报文段,这会导致TCP服务器反复重传连接释放报文段,并一直处于最后确认状态而无法进入关闭状态
因此,时间等待状态以及处于该状态2MSL
时长,可以确保服务器可以收到最后一个确认报文段而进入关闭状态
另外,客户端发送完最后一个确认报文段后,再经过2MSL时长,就可以使本次连接持续时间内所产生的所有报文段都从网络中消失,这样就可以使下一个新的连接中不会出现旧连接中的报文段