重要
最重要的事:
1.简介
seq: 序号,TCP连接中传送的字节流中的每个字节都按顺序编号。
ack: 确认号,是期望收到对方下一个报文的第一个数据字节的序号。
SYN: 同步SYN,在连接建立时用来同步序号。当SYN=1,ACK=0,表明是连接请求报文,若同意连接,则响应报文中应该使SYN=1,ACK=1
ACK: 确认ACK,仅当ACK=1时,确认号字段才有效。TCP规定,在连接建立后所有报文的传输都必须把ACK置1;
FIN: 终止FIN,用来释放连接。当FIN=1,表明此报文的发送方的数据已经发送完毕,并且要求释放;
三次握手
过程:
x= 随机生成序列号
y= 随机生成序列号
客户端[SYN_SENT ]—-SYN=1,seq=x (请求连接)——————->[ ]服务端
客户端[ ]<—SYN=1,ACK=1,ack=x+1,seq=y(应答客户端SYN,并请求建立连接)–>[SYN_RCVD ]服务端
客户端[ESTABLISHED]–ACK=1,ack=Y+1 (应答服务端SYN)—————>[ESTABLISHED]服务端
三次握手而非两次的原因:
如果客户端发送请求连接-1
,由于网络原因超时,客户端重试再次发出请求连接-2
,此时正常建立连接并完成通信;
之后网络回复请求连接-1
再次送达服务端, 此时服务端响应的应答客户端SYN请求
被返回客户端,此时客户端不会再
发出应答服务端端SYN请求
,server收不到确认请求,则不会建立连接。
四次挥手
过程:
断开过程由客户端或服务端任一方执行close来触发。TCP连接是全双工的,因此,每个方向都必须要单独进行关闭
x=等于前面已经传送过来的数据的最后一个字节的序号加1
y=自身序列号
z=服务端释放的报文可能携带数据
客户端[FIN_WAIT_1]—-FIN=1,seq=x (client请求释放)———–>[ ]服务端
客户端[FIN_WAIT_1]<—ACK=1,ack=x+1,seq=y (释放确认报文)————–>[CLOSE-WAIT ]服务端
客户端[FIN_WAIT_2]<—FIN=1,ACK=1,ack=y+1,seq=z (server请求释放)————[LAST-ACK ]服务端
客户端[TIME-WAIT ]—-ACK=1,ack=z+1,seq=y+1 (最终释放确认报文)———–>[CLOSE ]服务端
2∗MSL(最长报文段寿命)的时间后,当客户端撤销相应的TCB后,才进入CLOSED状态。
客户端[CLOSE]
为什么客户端最后还要等待2MSL?
MSL(Maximum Segment Lifetime), 报文段最大生存时间,它是任何报文段被丢弃前在网络内的最长时间。
第一,保证TCP协议的全双工连接能够可靠关闭
保证客户端发送的最后一个ACK报文能够到达服务器,因为这个ACK报文可能丢失,
站在服务器的角度看来,我已经发送了FIN+ACK报文请求断开了,客户端还没有给我回应,
应该是我发送的请求断开报文它没有收到,于是服务器又会重新发送一次,
而客户端就能在这个2MSL时间段内收到这个重传的报文,接着给出回应报文,并且会重启2MSL计时器。
第二,保证这次连接的重复数据段从网络中消失
防止类似与“三次握手”中提到了的“已经失效的连接请求报文段”出现在本连接中。
客户端发送完最后一个确认报文后,在这个2MSL时间中,就可以使本连接持续的时间内所产生的所有报文段都从网络中消失。
这样新的连接中不会出现旧连接的请求报文。
为什么建立连接是三次握手,关闭连接确是四次挥手呢?
建立连接的时候,服务器在LISTEN状态下,收到建立连接请求的SYN报文后,把ACK和SYN放在一个报文里发送给客户端。
而关闭连接时,服务器收到对方的FIN报文时,仅仅表示对方不再发送数据了但是还能接收数据,而自己也未必全部数据都发送给对方了,
所以己方可以立即关闭,也可以发送一些数据给对方后,再发送FIN报文给对方来表示同意现在关闭连接,
因此,己方ACK和FIN一般都会分开发送,从而导致多了一次。