TCP协议“三次握手”与“四次挥手”详解(下)
前面进行“三次握手”建立连接后,当客户端的数据发送完毕,它就会要求与服务器端断开连接,那么就要进行“四次挥手”进行连接的释放。
注意,此处所谓的“客户端”与“服务器端”,只是为了方便标识连接的双方,即确认哪一方是“要求断开连接”的主动方,哪一方是“要求断开连接”的被动方。事实上任何一方都可能在发送完数据后要求与另一方断开连接。
1、“四次挥手”过程
如下图:
“四次挥手”的具体过程如下:
1)“第一次挥手”:首先,客户端已经发送完数据,想要释放连接(客户端是释放连接的主动方),向服务器端发送一段TCP报文,其中:
i)标记位 FIN=1:表示这个TCP请求是“请求释放连接”;
ii)报文的序号 seq=u:u 等于前面客户端已经传送的数据的最后一个字节的序号加1;
iii)客户端由“ESTABLISHED”连接建立状态,进入“FIN-WAIT-1”终止等待状态1。此时客户端不会再向服务器端发送数据。
需要注意,FIN报文虽然不携带数据,但是但是它会消耗一个字节序号。即客户端第一次发送的FIN报文 seq=u,报文会消耗一个序号,那么客户端下次发送的报文应该从 seq=u+1 开始发送。
2)“第二次挥手”:服务器端接收到从客户端发出的TCP报文之后,确认了客户端想要释放连接,会发送回一个TCP报文,其中:
i)标记位为ACK=1:表示“服务器端告知客户端,自己已经接收到客户端发送的释放连接的请求”;
ii)报文序号 seq=v:服务器端到客户端的连接还没有关闭,服务器端还会向客户端发送数据包,这个报文序号为 v;
iii)确认号ack = u+1:表示希望客户端下一个报文的序号是 u+1,即希望客户端下一个报文从序号为 u+1 的字节开始发送。我们知道客户端第一个报文 seq=u,且该报文为FIN报文,占一个序号,那么客户端下一个报文就应该从 u+1 开始发送。
iv)服务器端结束 “ESTABLISHED” 连接阶段,进入“CLOSE-WAIT” 关闭等待状态;
此时从 客户端到服务器端 这个方向的连接就被释放,TCP连接处于“半关闭状态” 。 此时客户端不会再向服务器端发送数据,但是服务器端可能还会想客户端发送数据。
v)客户端收到从服务器端发出的TCP报文之后,确认了服务器端收到了客户端发出的释放连接请求,随后客户端结束“FIN-WAIT-1”终止等待状态1,进入“FIN-WAIT-2”终止等待状态2。
总结:前两次挥手,既让服务器端知道了客户端想要释放连接,也让客户端知道了服务器端知道了自己想要释放连接。
3)“第三次挥手”:客户端经过 “ClOSE-WAIT” 关闭等待 状态后,它要发送给服务器端的数据也发送完毕,即它做好了释放服务器端到客户端连接的准备,就会想客户端发送一段FIN的TCP报文:
i)标记位 FIN=1,ACK=1:表示“服务器端告知客户端,自己已经做好释放连接的准备”;
ii)报文序号 seq=w:关闭等待阶段,服务器端可能又向客户端发送了数据,因此此时 seq 不是v,而是最新的数据 w;
iii)确认号 ack=u+1:还是希望客户端下一次发送的报文序号为 u+1;
iv)发送“第三次挥手”报文后,服务器端进入“LAST-ACK” 最后确认阶段。此后,服务器端再也无法向客户端发送数据。
注意,第三次挥手发送的是FIN的报文,没有数据但是会占一个序号,即下一次服务器端发送的报文序号 seq=w+1。
4)“第四次挥手”:客户端接收到服务器端“第三次挥手”的报文后,确认服务器端已经做好断开连接的准备,会向客户端发送“第四次握手”的报文:
i)标记位ACK=1:表示“客户端已经知道服务器端做好释放连接的准备”;
ii)ack = w+1:将收到服务器端报文的 seq+1,作为自己的ack。表示希望服务器端下次发送的报文的序号为 w+1;
iii)seq=u+1:将收到服务器端报文的 ack 作为自己的 seq,因为服务器端报文 ack=u+1 表示希望客户端这次发送的报文序号是 u+1,那么客户端这次发送报文的序号就设置为 u+1;
iv)客户端发送完第四次挥手的报文后,启动等待计时器,等待2MSL后,如果没有收到服务器端新的请求,就进入“CLOSED” 连接关闭状态;
v)服务器端在收到客户端发送的第四次挥手的报文后,进入进入“CLOSED” 连接关闭状态。
总结:后“两次挥手”既让客户端知道了服务器端准备好释放连接了,也让服务器端知道了客户端了解了自己准备好释放连接了。于是,可以确认关闭服务器端端到客户端方向上的连接了,由此完成“四次挥手”,关闭了连接。
2、三个关键问题
1)为什么“握手”是三次,而“挥手”却是四次?
对于“三次握手”,在第二次握手的时候,服务器端向客户端发送的报文的标记位包含 SYN=1以及ACK=1,SYN是请求连接标志,表示服务器端同意建立连接;ACK是确认报文,表示告诉客户端,服务器端收到了它的请求报文。即“确认接收”与“同意连接”是在同一次握手中传输的。那么通过三次握手就刚刚好可以建立连接;
对于“四次挥手”,第二次挥手的时候,服务器端可能还没有做好关闭连接的准备(它可能还有数据要发送给客户端),因此,它不会立即释放连接,会在第二次挥手先返回一个ACK=1,表示已经接受到客户端的断开连接的请求。随后,客户端处理完数据后,会发送第三次挥手报文,其中FIN=1,表示服务器端已经准备好释放连接。因此,释放连接需要经过“四次挥手”。
2)为什么客户端要在发送第四次挥手的报文后等待2MSL的时间才进入CLOSED状态?
目的是为了确认服务器端会收到客户端发送的“第四次挥手”的ACK确认报文。
MSL(Max Segment Lifetime): 最长报文段寿命,也就是一个报文在网络中存活的最长时间,一般设置为2分钟。当客户端发出最后的ACK确认报文时,并不能确定服务器端能够收到该段报文。所以客户端在发送完ACK确认报文之后,会设置一个时长为2MSL的计时器。
在1MSL的时候,如果服务器端没有收到客户端发送的ACK确认报文,就会再次向客户端发送FIN报文,这个报文在1MSL的时间内会到达客户端,此时客户端边知道自己上一次发送的ACK确认报文没有发送到服务器端,于是客户端会再次向服务器端发送ACK确认报文,并将等待计时器重置。
如果在2MSL的时间内没有接受到服务器端发送回来的FIN报文,说明客户端最后发送的ACK确认报文已经被服务器端接收到,可以关闭连接。因此,事实上客户端会比服务器端更晚进入CLOSED状态。
3)如果已经建立了连接,但是客户端出现故障了怎么办?
如果客户端发送错误,服务器端还一直保持连接,这个连接并不会传送数据,并且占用了服务器端的资源。服务器端有一个“保活计时器”,服务器端每收到一次客户端的请求后都会重新复位这个计时器,时间通常是设置为2小时,若2小时还没有收到客户端的任何数据,客户端就会发送一个探测报文段,以后每隔75秒钟发送一次。若一连发送10个探测报文客户端仍然没反应,服务器端就认为客户端出了故障,接着就关闭连接。
TCP协议“三次握手”与“四次挥手”详解(下)的更多相关文章
- TCP协议三次握手与四次挥手详解
在计算机网络的学习中TCPi协议与Http协议是我们必须掌握的内容,其中Tcp协议属于传输层,而Http协议属于应用层,本博客主要讲解Tcp协议中的三次握手与四次挥手,关于Http协议感兴趣的可以参看 ...
- TCP协议“三次握手”与“四次挥手”详解(上)
在使用TCP协议进行数据的传输之前,客户端与服务器端需要建立TCP Connection,即建立连接,之后两端才能进行数据的传输. 下面堆TCP连接“三次握手”的过程进行说明. 1.相关概念 首先,我 ...
- TCP的三次握手与四次挥手详解
TCP的三次握手与四次挥手是TCP创建连接和关闭连接的核心流程,我们就从一个TCP结构图开始探究中的奥秘 序列号seq:占4个字节,用来标记数据段的顺序,TCP把连接中发送的所有数据字节都编上一个序 ...
- TCP的三次握手和四次挥手详解
相对于SOCKET开发者,TCP创建过程和链接折除过程是由TCP/IP协议栈自动创建的.因此开发者并不需要控制这个过程.但是对于理解TCP底层运作机制,相当有帮助. TCP报文格式 TCP的包如下: ...
- TCP三次握手与四次挥手详解
目录 TCP三次握手与四次挥手详解 1.TCP报文格式 2.TCP三次握手 3.TCP四次挥手 4.为什么建立连接需要三次握手? 5.为什么断开连接需要四次挥手? 6.为什么TIME_WAIT状态还需 ...
- TCP/IP的三次握手与四次挥手详解
TCP((Transmission Control Protocol)传输控制协议,是一个面向连接的协议.在运用此协议进行数据传输前都会进行连接的建立工作(三次握手):当数据传输完毕,连接的双方都会通 ...
- TCP三次握手与四次挥手详解(最全面)
目录 TCP的三次握手与四次挥手 TCP报文段的首部格式 TCP的工作原理 TCP 的流量控制 TCP的拥塞控制 拥塞控制与流量控制的关系 拥塞控制所起的作用 慢开始和拥塞避免 慢开始算法的原理 三次 ...
- TCP协议三次握手与四次挥手通俗解析
TCP/IP协议三次握手与四次握手流程解析 一.TCP报文格式 TCP/IP协议的详细信息参看<TCP/IP协议详解>三卷本.下面是TCP报文格式图: 图1 TCP报文格式 上图中有几个字 ...
- [ 转载 ] Tcp三次握手和四次挥手详解
#TCP的报头: 源端口号:表示发送端端口号,字段长为16位.目标端口号:表示接收端口号,字段长为16位.序列号:表示发送数据的位置,字段长为32位.每发送一次数据,就累加一次该数据字节数的大小.注意 ...
随机推荐
- Netty源码死磕一(netty线程模型及EventLoop机制)
引言 好久没有写博客了,近期准备把Netty源码啃一遍.在这之前本想直接看源码,但是看到后面发现其实效率不高, 有些概念还是有必要回头再细啃的,特别是其线程模型以及EventLoop的概念. 当然在开 ...
- HTML5新特性--svg-echarts(重点)-拖动API-WebWorker
一.html5新特性--svg--(折线/渐变特效对象/滤镜) #折线:多个坐标点组件一条折线 <polyline points="50,50 70,55 60,66 " s ...
- BZOJ4260异或和
4260: Codechef REBXOR Time Limit: 10 Sec Memory Limit: 256 MBSubmit: 918 Solved: 420[Submit][Statu ...
- 【Spring】Spring AOP详解(转载)
一.前言 在以前的项目中,很少去关注spring aop的具体实现与理论,只是简单了解了一下什么是aop具体怎么用,看到了一篇博文写得还不错,就转载来学习一下,博文地址:http://www.cnbl ...
- thinkphp5.0 cache缓存机制
首先引用缓存文件 use think\Cache; public function index(){ $data = Cache::get('showw');//去缓存 if($data){ echo ...
- AspectJ JoinPoint及ProceedingJoinPoint 简要api文档
AspectJ使用org.aspectj.lang.JoinPoint接口表示目标类连接点对象,如果是环绕增强时,使用org.aspectj.lang.ProceedingJoinPoint表示连接点 ...
- Python学习之路【第一篇】:Python简介与入门
Python简介 一.什么是Python Python 是一个高层次的结合了解释性.编译性.互动性和面向对象的脚本语言. Python 的设计具有很强的可读性,相比其他语言经常使用英文关键字,其他语言 ...
- centos6.4中文输入法
在虚拟机中装了centos6.4之后,一直使用命令行,没有用到编辑器编辑中文或者浏览器中文搜索,所以没有注意到里边中文输入的重要性.在网上有看到说如果用的是中文版本应该有自带的中文输入法,然后用快捷键 ...
- 练习使用shell在阿里云安装MySQL
#!/bin/bash #阿里云初始安装MySQL #step1:查寻MariaDB 并卸载 MariaDB_filename=`rpm -qa|grep mariadb` if [ -d " ...
- SpringBoot实现微信小程序登录的完整例子
目录 一.登录流程 二.后端实现 1.SpringBoot项目结构树 2.实现auth.code2Session 接口的封装 3.建立用户信息表及用户增删改查的管理 4.实现登录认证及令牌生成 三.前 ...