TCP协议结构简介
TCP在IP中的封装
以下为TCP在IP数据报中的封装
TCP头部
源端口和目的端口
一个IP地址和端口的组合称为“套接字”或“端点”。
所以IP协议中的源IP地址和目的地址
和TCP协议中的源端口和目的端口,
组成了“一对”套接字(发送端的套接字和接收端的套接字)。
序列号
每一个“TCP报文段中的第一个字节”都会被赋予一个序列号。
序列号是个32位数,到达2^32-1后会再回到0.
确认号(TCP返回报文使用)
也称ACK号或ACK字段。
确认号包含的值为:“确认号的发送方”希望接收的下一个序列号。(即最后接收成功的序列号+1)
头部长度
该字段表示TCP头部的长度,以32位字为单位。
由于“选项字段”大小是可变的,所以“头部长度”字段是必须的。
TCP头部长度最大为60字节,如果没有选项字段,则为20个字节。
8种状态标识
以下各个标识表示了“该TCP报文段”是干什么的。
如:
SYN和ACK可能同时为1,它表示的就是建立连接之后的响应。
单个的一个SYN,它表示的只是建立连接。
1、CWR:拥塞窗口减(发送方降低它的发送速率)。
2、ECE:ECN回显(发送方接收到了一个更早的拥塞通告)
3、URG:紧急(紧急指针字段有效,很少用)
4、ACK:确认(确认号字段有效,连接建立后一般都是启用状态)
5、PSH:推送(几乎没被用到)
6、RST:重置连接(连接取消)
7、SYN:表示建立连接
8、FIN:该报文的发送方已经结束向对方发送数据
窗口大小
在TCP协议里,一个分组从发送端发送到接收端后,接收端应该返回一个ACK号。
如之前所说,每一个分组都是从“序列号”开始的,我们定一个术语“窗口”,来表示:已发送的分组们,但这些分组还未返回确认号(ACK号)。
窗口中的分组数量称之为:“窗口大小”。
下图为发送方的窗口以及其他分组队列:
如图所示,如果发送方下一步接收到了序列号为4的分组的“ACK”,则“窗口向右滑动一个分组”,意味着分组4可以释放了,分组7可以发送了。这种行为称之为:“窗口滑动协议”。
TCP校验和
该校验算法与IP、ICMP、UDP校验算法一致,其覆盖了TCP头部和数据中的一些字段。
紧急指针
只有在有URG字段时才有效。该指针是一个加到“序列号字段”上的正偏移,以产生“紧急数据”的最后一个字节的序列号。
选项
最常见的选项字段为:“最大段大小”字段,称为MSS。
连接的每个端点(套接字)一般在它发送的第一个报文段上指定该选项。
下面我们会详讲这些额外“选项”。
TCP连接
TCP连接的建立与终止
一个TCP连接由一个4元组构成,它们分别是发送端ip地址,发送端tcp端口,接收端ip地址,接收端tcp端口。也就是说,tcp连接由一对套接字构成。
TCP连接通常分为3个阶段:启动、数据传输(连接已建立)、退出(连接关闭)。
过程如下图:
建立连接
第一次握手:(问服务端“你能不能听见我说话?”)
客户端主动发送一个TCP报文段,
里面SYN字段设为1(表示建立连接,即“询问”),且包含了该报文段的初始“序列号”(记为ISN(c),该初始序列号是随机产生的)。
通常,客户端还会借此发送多个“选项”。
第二次握手:(回答客户端说“能听见你说话”,但问客户端“你能不能听见我说话?”)
服务端也发送自己的TCP报文段作为响应,
里面的SYN和ACK字段设为1(表示建立连接之后的响应,即询问+响应)。
该报文段的序列号为它自己的初始“序列号”(记为ISN(c),该初始序列号是随机产生的)。
该报文段还包含“确认号”,为“第一次握手时获得的ISN(c)+1”。(之前讲过,确认号表示:“确认号的发送方希望接收的下一个序列号”。即接收成功的序列号+1)
第三次握手:(回答服务端说“能听见你说话”)
客户端响应服务端,
里面的ACK字段为1(即响应)。
该报文段的序列号为ISN(c)+1(刚好与第二次握手的确认号相呼应)。
确认号为ISN(s)+1(即第二次握手中的序列号+1)
关闭连接
连接的双方都能关闭连接,但传统情况下是客户端负责发起关闭连接。
1、连接的主动关闭者(图中为客户端)发送一个FIN=1(表示已经结束向对方发送数据)和ACK=1(表示接收到了之前发送过来的最后一个数据)的报文段。
2、被动关闭者,先发个ACK报文段,表示:已经接收到刚刚的报文了。再发个ACK+FIN报文字段,此时被动关闭者的身份又转换成了主动关闭者,表示它也要关闭了。
3、最后,客户端发送一个ACK报文表示知道了。
TCP半关闭
所谓半关闭就是:
关闭的发起端发送了“要求关闭的报文”,(客户端发送:FIN+ACK)
接收端返回响应表示接收到了(服务端发送:ACK)
但被动关闭方可能数据没传完,所以继续传了很多数据给发起端,
然后发起端确认接收到这些数据了,
然后被动关闭方再发送“关闭报文”(服务端发送:FIN(此时没有ACK了,因为ACK的作用是表示“接收到了你发来的报文”,而客户端已经没有发来报文了))
客户端发个响应表示知道了(客户端发送:ACK),TCP连接关闭。
(即:连接的一方关闭,另一方仍然传输数据直到它关闭为止)
同时打开与关闭
所谓同时打开关闭就是:
通信双方在接收到来自对方的SYN报文段(SYN=1表示建立连接)之前,双方都要先给对方发送一个SYN报文。
然后双方再响应各自收到的报文(即双方都再发送SYN+ACK报文段)。
TCP选项
之前说过了,TCP头部包含了多个可选的“选项”字段。
下面详细介绍几个比较常用的选项:
最大段大小选项(MSS)
最大段大小是指TCP协议所能允许的从对方接收到的最大报文段(即通信对方所能使用的最大报文段)。
当建立一条TCP连接时,通信的每一方都应在SYN报文段的MSS选项中说明自己所允许的“最大报文段”。
最大段的默认大小为:536字节。
选择确认选项(SACK)
在没有加这个选项之前,假设发送端按序发送给接收端5个分组报文,
客户端发送第1个,接收端返回ACK表示确认。
客户端发送第2个,中途出了问题没法送到。接收端返回响应表示刚刚的数据2报文错误。
客户端发送第3个,(客户端不能响应,因为没正确的接收到数据2)
客户端发送第4个,(客户端不能响应,因为没正确的接收到数据2)
此时客户端收到报文2的错误响应。
客户端再发送第2个,接收端返回ACK表示确认。
客户端再发送第3个,接收端返回ACK表示确认。
客户端再发送第4个,接收端返回ACK表示确认。
······
由此可看出,客户端重复的发送了2以后的报文。
如果“TCP接收方”能提供“选择确认选项(SACK)”,
那么服务端即使没接收到数据2,也依然会正常接收数据2以后的报文。
用户超时选项(UTO)
用户超时数值指明了TCP发送者愿意等待ACK确认的时间。
认证选项(TCP-AO)
该选项使用一种散列加密算法以及连接双方共同维护一个秘密值来认证每一个报文段。
TCP认证选项不仅提供各种加密算法,还使用带内信令来确认秘钥是否改变。
TCP状态转换
之前提到了TCP在不同的阶段会发送各种各样的报文段,而这些决定TCP应该做什么的规则,其实是由TCP所属的“状态”决定的。
而TCP的状态会在各种触发条件下改变。
我们还是来看一下TCP的连接与关闭:
ESTABLISHED是通信双方双向传输数据的状态。
FIN_WAIT_1,FIN_WAIT_2,TIME_WAIT称作:“主动关闭”状态。
它们表示当本地应用程序发起一个请求时会进入的状态集合。
CLOSE_WAIT,LAST_WAIT表示“被动关闭”,
这些状态与等待一个节点确认一个FIN报文段相关。