tcp连接与断开连接图解

建立连接非常重要,它是数据正确传输的前提;断开连接同样重要,它让计算机释放不再使用的资源。如果连接不能正常断开,不仅会造成数据传输错误,还会导致套接字不能关闭,持续占用资源,如果并发量高,服务器压力堪忧。
建立连接需要三次握手,断开连接需要四次握手,可以形象的比喻为下面的对话:
[shake 1] 套接字a:“任务处理完毕,我希望断开连接。”
[shake 2] 套接字b:“哦,是吗?请稍等,我准备一下。”
等待片刻后……
[shake 3] 套接字b:“我准备好了,可以断开连接了。”
[shake 4] 套接字a:“好的,谢谢合作。”
下图演示了客户端主动断开连接的场景:
建立连接后,客户端和服务器都处于establised状态。这时,客户端发起断开连接的请求:
1) 客户端调用 close() 函数后,向服务器发送 fin 数据包,进入fin_wait_1状态。fin 是 finish 的缩写,表示完成任务需要断开连接。
2) 服务器收到数据包后,检测到设置了 fin 标志位,知道要断开连接,于是向客户端发送“确认包”,进入close_wait状态。
注意:服务器收到请求后并不是立即断开连接,而是先向客户端发送“确认包”,告诉它我知道了,我需要准备一下才能断开连接。
3) 客户端收到“确认包”后进入fin_wait_2状态,等待服务器准备完毕后再次发送数据包。
4) 等待片刻后,服务器准备完毕,可以断开连接,于是再主动向客户端发送 fin 包,告诉它我准备好了,断开连接吧。然后进入last_ack状态。
5) 客户端收到服务器的 fin 包后,再向服务器发送 ack 包,告诉它你断开连接吧。然后进入time_wait状态。
6) 服务器收到客户端的 ack 包后,就断开连接,关闭套接字,进入closed状态。
tcp建立过程(三次握手) 所谓三次握手(three-way handshake)即建立tcp连接,就是指建立一个tcp连接时,需要客户端和服务端总共发送3个包以确认连接的建立。
(1)第一次握手:client将标志位syn置为1,随机产生一个值seq=j,并将该数据包发送给server,client进入syn_sent状态,等待server确认。
(2)第二次握手:server收到数据包后由标志位syn=1知道client请求建立连接,server将标志位syn和ack都置为1,ack=j+1,随机产生一个值seq=k,并将该数据包发送给client以确认连接请求,server进入syn_rcvd状态。
(3)第三次握手:client收到确认后,检查ack是否为j+1,ack是否为1,如果正确则将标志位ack置为1,ack=k+1,并将该数据包发送给server,server检查ack是否为k+1,ack是否为1,如果正确则连接建立成功,client和server进入established状态,完成三次握手,随后client与server之间可以开始传输数据了。
注意:三次握手的序列号和确认号,如果用(序列号,确认号)表示一次握手,则三次握手的过程序列号和确认号如下:
1) 第1步:客户端向服务器发送一个同步数据包请求建立连接,该数据包中,初始序列号(isn)是客户端随机产生的一个值,确认号是0;
2) 第2步:服务器收到这个同步请求数据包后,会对客户端进行一个同步确认。这个数据包中,序列号(isn)是服务器随机产生的一个值,确认号是客户端的初始序列号+1;
3) 第3步:客户端收到这个同步确认数据包后,再对服务器进行一个确认。该数据包中,序列号是上一个同步请求数据包中的确认号值,确认号是服务器的初始序列号+1。
1、(x,0)
2、(y,x+1)
3、(x+1,y+1)
tcp断开连接过程(四次挥手) 【注意】中断连接端可以是client端,也可以是server端。
假设client端发起中断连接请求,也就是发送fin报文。server端接到fin报文后,意思是说“我client端没有数据要发给你了”,但是如果你还有数据没有发送完成,则不必急着关闭socket,可以继续发送数据。所以你先发送ack,“告诉client端,你的请求我收到了,但是我还没准备好,请继续你等我的消息”。这个时候client端就进入fin_wait状态,继续等待server端的fin报文。当server端确定数据已发送完成,则向client端发送fin报文,“告诉client端,好了,我这边数据发完了,准备好关闭连接了”。client端收到fin报文后,“就知道可以关闭连接了,但是他还是不相信网络,怕server端不知道要关闭,所以发送ack后进入time_wait状态,如果server端没有收到ack则可以重传。“,server端收到ack后,”就知道可以断开连接了“。client端等待了2msl后依然没有收到回复,则证明server端已正常关闭,那好,我client端也可以关闭连接了。ok,tcp连接就这样关闭了!
由于tcp连接时全双工的,因此,每个方向都必须要单独进行关闭,这一原则是当一方完成数据发送任务后,发送一个fin来终止这一方向的连接,收到一个fin只是意味着这一方向上没有数据流动了,即不会再收到数据了,但是在这个tcp连接上仍然能够发送数据,直到这一方向也发送了fin。首先进行关闭的一方将执行主动关闭,而另一方则执行被动关闭,上图描述的即是如此。
(1)第一次挥手:client发送一个fin,用来关闭client到server的数据传送,client进入fin_wait_1状态。
(2)第二次挥手:server收到fin后,发送一个ack给client,确认序号为收到序号+1(与syn相同,一个fin占用一个序号),server进入close_wait状态。
(3)第三次挥手:server发送一个fin,用来关闭server到client的数据传送,server进入last_ack状态。
(4)第四次挥手:client收到fin后,client进入time_wait状态,接着发送一个ack给server,确认序号为收到序号+1,server进入closed状态,完成四次挥手。
四次挥手的序列号和确认号
(u,0)
(v,u+1)
(w,u+1)
(u+1,w+1)
上面是一方主动关闭,另一方被动关闭的情况,实际中还会出现同时发起主动关闭的情况,具体流程如下图:
【问题1】为什么连接的时候是三次握手,关闭的时候却是四次握手?
答:因为当server端收到client端的syn连接请求报文后,可以直接发送syn+ack报文。其中ack报文是用来应答的,syn报文是用来同步的。但是关闭连接时,当server端收到fin报文时,很可能并不会立即关闭socket,所以只能先回复一个ack报文,告诉client端,”你发的fin报文我收到了“。只有等到我server端所有的报文都发送完了,我才能发送fin报文,因此不能一起发送。故需要四步握手。
【问题2】为什么time_wait状态需要经过2msl(最大报文段生存时间)才能返回到close状态?
答:虽然按道理,四个报文都发送完毕,我们可以直接进入close状态了,但是我们必须假象网络是不可靠的,有可以最后一个ack丢失。所以time_wait状态就是用来重发可能丢失的ack报文。
为什么是2msl,主要是为了考虑到如果最后一个ack丢失,服务端会重新发fin,客户端等待2msl,才能接收到服务端重新发送的fin报文。
【问题3】rst的作用
rst表示复位,用来异常的关闭连接,在tcp的设计中它是不可或缺的。就像上面说的一样,发送rst包关闭连接时,不必等缓冲区的包都发出去(不像上面的fin包),直接就丢弃缓存区的包发送rst包。而接收端收到rst包后,也不必发送ack包来确认。
tcp处理程序会在自己认为的异常时刻发送rst包。例如,a向b发起连接,但b之上并未监听相应的端口,这时b操作系统上的tcp处理程序会发rst包。
又比如,ab正常建立连接了,正在通讯时,a向b发送了fin包要求关连接,b发送ack后,网断了,a通过若干原因放弃了这个连接(例如进程重启)。网通了后,b又开始发数据包,a收到后表示压力很大,不知道这野连接哪来的,就发了个rst包强制把连接关了,b收到后会出现connect reset by peer错误。
【问题4】当urg=1时
紧急比特urg——当urg=1时,表明紧急指针字段有效。它告诉系统此报文段中有紧急数据,应尽快传送(相当于高优先级的数据)。

智慧集成供水系统方案
中国CCC强制认证的产品范围分享
四维图新相关企业杰发科技、六分科技荣获知鼎奖-智能电动汽车科技创新奖
人工智能和物联网之间如何协同合作
教你如何选择更正确的kvm切换器?
tcp连接与断开连接图解
有史以来最高人工智能单笔融资,商汤科技到底是有多值钱
从信息通信网络的“覆盖普及”,转为高质量发展
Python为什么那么受欢迎?比之其他有何优点?
商汤AI新药研发成果登上国际权威科学杂志「Nature」子刊
dfrobot10自由度惯性导航模块简介
调速电机怎么调速 调速电机的五根调速线如何接
人工智能挑战人类,OpenAI机器人打败游戏玩家
使用 NVIDIA DeepStream SDK 6.2 顺利开发视觉 AI 应用
针灸针弹性韧性刚性针尖穿刺力针体连接牢固度测试
微软将推广首款安卓旗舰机Surface Duo
远程开关控制器怎么设置定时?
著名经济学家魏杰:中美贸易战期间企业应以稳为主
2020 WAIC黑客松:16支团队收获佳绩,软银机器人赛道亮点纷呈!
“中国制造”之所以有今天,原因无他,纯属咎由自取