程序员面试之必考题(二):TCP连接的建立和拆除

TCP 是面向连接的传输协议,其连接功能是通过 TCP 的连接管理实现的, TCP 连接管理包括连接建立、数据传输和连接拆除三个阶段。 TCP 连接建立过程中要解决以下三个问题:


1 )要使通信的双方能够确知对方的存在。

2 )要允许双方协商通信过程中的相关参数。

3 )能够对传输实体的资源进行分配。


TCP 连接的建立采用客户 / 服务器方式。主动发起连接建立的应用进程为客户,被动等待连接建立的应用进程为服务器。 TCP 连接的建立过程可以形象的描述为“三次握手”,其过程如下(如图 1 所示):


第一次握手:客户端作为连接建立发起端,选择客户端初始序列号 x ,向服务器发送( SYN=1 seq=x )的 SYN 段。客户状态由 LISTEN 进入 SYN SEND 状态,等待服务器确认。


第二次握手:服务器收到客户发送的 SYN 段后,选择服务器初始序列号 y ,向客户发送( SYN=1 ACK=1 seq=y ack_seq=x+1 )的 SYNACK 段。同时,服务器状态也由 LISTEN 进入 SYN RCVD 状态。


第三次握手:客户端收到服务器的 SYNACK 段后,向服务器发送( ACK=1 seq=x ack_seq=y+1 )的 ACK 段,同时,客户端状态进入 ESTABLISHED 状态,客户端确认连接已建立;当服务器收到 ACK 段后,其状态也进入 ESTABLISHED 状态,也确认连接已建立。至此,双方均确认连接建立成功。


TCP 连接建立过程中的第一次握手与第二次握手发送的 SYN 段和 SYNACK 段,均不封装应用层数据,即数据字段为空,但这两个端均需消耗一个序列号。也就是说,客户端的初始序列号 x SYN 用掉,服务器端的初始序列号 y SYNACK 段用掉。客户向服务器发送的应用层数据的第一个字节序号是 x+1 ,服务器发送给客户的应用层数据的第一个字节序号是 y+1 。另外,第三次握手的 ACK 段是可以封装应用层数据的,但是单纯的 ACK 段(即未封装应用层数据)是不消耗序列号的。


TCP 的连接建立完成后,就可以进行数据传送。数据传送结束后,还需要进行连接拆除, TCP 的连接拆除需要经过四次握手过程


(1) 当客户向服务器发送完最后一个数据段后,可以发送一个FIN段(FIN=1seq=u),请求断开客户到服务器的(半)连接。FIN段不封装应用层数据,但是要消耗掉一个序列号(类似于SYN段),其状态由ESTABLISHED进入FIN_WAIT_1,在这一状态下,只能接收服务器发送过来的数据,而不再发送数据。


(2) 服务器收到客户的FIN段后,向客户发送一个ACK段(ACK=1seq=vack_seq=u+1),ACK段可以封装应用层数据(如果有)。服务器状态ESTABLISHED进入CLOSE_WAIT,在这一状态下,服务器仍然可以发送数据,而不再接收数据。当客户收到ACK段后,其状态由FIN_WAIT_1进入FIN_WAIT_2,仍然可以接收来自服务器的数据。此时的TCP连接已经关闭了客户向服务器方向的数据传输,故也称为半关闭。


(3) 当服务器向客户发送完最后一个数据段后,服务器向客户 FIN 段( FIN=1 ACK=1seq=wack_seq=u+1),同样,该FIN段也不携带应用层数据。服务器状态则由CLOSE_WAIT进入LAST_ACK,此时服务器也不再发送数据。

(4) 当客户收到服务器发送的FIN段后,向服务器发送ACK段(ACK=1seq=u+1ack_seq=w+1),其状态由FIN_WAIT_2进入TIME_WAIT,等待2MSLMaximum Segment Lifetime)时间,然后进入CLOSED状态,最终释放连接;服务器在收到最后一次ACK段后,状态由LAST_ACK进入CLOSED,最终释放连接。


MSL 是最大段生存时间,是任何 TCP 段被丢弃前在网络内 存活 的最长时 间。TCP协议规范(RFC793)规定的MSL2分钟,但实际系统在实现TCP时设定的时间有所不同,比如BSD/38630秒、Soloris 2.21分钟。客户在TIME_WAIT状态之所以要等待2MSL时间才真正释放连接,一方面是为了以防最后一次ACK段丢失,会导致服务器重发FIN,这样在客户真正释放连接前还可以再次发送ACK段,尽可能确保服务器尽快释放连接,另一方面是为了保证在2MSL期间,该连接的本地端点地址(IP地址和端口号)不被再次使用,避免可能的较早连接请求到达,被误解为新连接请求。


另外,如果服务器收到客户发送的FIN段(第一次挥手),刚好服务器向客户发送的最后一个数据段也发送完了,此时第二次挥手的ACK段和第三次挥手的FIN段可以合并为一个段发送。注意,这个段是不封装应用层数据的,但是作为FIN段仍然要消耗掉一个序列号。

转自微信公众号:开点工作室(ID:kaidiancs)
全部评论
原文有,贴过来不知道怎么回事就丢失了
点赞 回复 分享
发布于 2016-06-06 12:11
没有图片
点赞 回复 分享
发布于 2016-06-05 10:49

相关推荐

豆泥🍀:同26届,加油,我也还没找到查看图片
点赞 评论 收藏
分享
评论
点赞
53
分享

创作者周榜

更多
牛客网
牛客企业服务