程序员面试之必考题(二):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

相关推荐

不愿透露姓名的神秘牛友
06-21 11:33
昨天是学校最后一场招聘会,鼠鼠去参加了,全场只有一个招聘java的岗位,上来先做一份笔试题,做完后他拿张纸对答案,然后开始问简历上的问题,深圳小厂,6-8k(题目如下),后面还有两轮面试。然后我就在招聘现场逛呀逛,看到有公司招聘电商运营,给的比上年的小厂还多,鼠鼠就去了解了下,然后hr跟鼠鼠要了份简历,虽然我的简历上面全是求职Java开发相关的内容,但是hr还是鼓励我说没关系,她帮我把简历给老板看看,下周一会给我通知。招聘会结束后鼠鼠想了一段时间,也和朋友聊了聊,发现我可能是不太适合这个方向,然后就跟爸爸说回家了给我发条微信,我有些话想跟他说说。晚上爸爸到家了,跟我发了条微信,我立马跑出图书馆跟他打起了电话,这个通话长达一个小时,主要是跟爸爸坦白说我不想找这行了,是你的儿子太没用了,想试试其他行业。然后爸爸也跟我说了很多,说他从来没有希望我毕业后就赚大钱的想法,找不到就回家去,回家了再慢慢找,实在找不到就跟他干(帮别人装修房子,个体户),他也知道工作不好找,让我不要那么焦虑,然后就是聊一些家常琐事。对于后面的求职者呢我有点建议想提一下,就是如果招实习的时间或者秋招开始,而你的简历又很差的情况下,不要说等做好项目填充完简历之后再投,那样就太晚了,建议先把熟悉的项目写上简历,然后边投边面边完善,求职是一个人进步的过程,本来就比别人慢,等到一切都准备好后再投岂不是黄花菜都凉了。时间够的话还是建议敲一遍代码,因为那样能让你加深一下对项目的理解,上面那些说法只是针对时间不够的情况。当然,这些建议可能没啥用,因为我只是一个loser,这些全是建立在我理想的情况下,有没有用还需其他人现身说法。上篇帖子没想到学校被人认了出来,为了不丢脸只能匿名处理了。
KPLACE:找研发类或技术类,主要还是要1.多投 2.多做准备,很多方面都要做准备 3.要有心理准备,投累了就休息一两天,再继续,要相信自己能找到
投递58到家等公司8个岗位
点赞 评论 收藏
分享
评论
点赞
53
分享

创作者周榜

更多
牛客网
牛客网在线编程
牛客网题解
牛客企业服务