TCP协议握手与分手
TCP的7次握手可以理解为3次握手和4次分手。
TCP状态转换图,如下:
这个图N多人都知道,它对排除和定位网络或系统故障时大有帮助,但是怎样牢牢地将这张图刻在脑中呢?那么你就一定要对这张图的每一个状态,及转换的过程有深刻地认识,不能只停留在一知半解之中。下面对这张图的11种状态详细解释一下,以便加强记忆!不过在这之前,先回顾一下TCP建立连接的三次握手过程,以及关闭连接的四次握手过程。
1、建立连接协议(三次握手)
(1)客户端发送一个带SYN标志的TCP报文到服务器。这是三次握手过程中的报文1。
(2) 服务器端回应客户端的,这是三次握手中的第2个报文,这个报文同时带ACK标志和SYN标志。因此它表示对刚才客户端SYN报文的回应;同时又标志SYN给客户端,询问客户端是否准备好进行数据通讯。
(3) 客户必须再次回应服务段一个ACK报文,这是报文段3。
2、连接终止协议(四次握手)
由于TCP连接是全双工的,因此每个方向都必须单独进行关闭。这原则是当一方完成它的数据发送任务后就能发送一个FIN来终止这个方向的连接。收到一个FIN只意味着这一方向上没有数据流动,一个TCP连接在收到一个FIN后仍能发送数据。首先进行关闭的一方将执行主动关闭,而另一方执行被动关闭。
(1)TCP客户端发送一个FIN,用来关闭客户到服务器的数据传送(报文段4)。
(2) 服务器收到这个FIN,它发回一个ACK,确认序号为收到的序号加1(报文段5)。和SYN一样,一个FIN将占用一个序号。
(3) 服务器关闭客户端的连接,发送一个FIN给客户端(报文段6)。
(4) 客户段发回ACK报文确认,并将确认序号设置为收到序号加1(报文段7)。
三次握手:
·第一次握手:建立连接时,客户端发送syn包(syn=j)到服务器,并进入SYN_SEND状态,等待服务器确认;
·第二次握手:服务器收到syn包,必须确认客户的SYN(ack=j+1),同时自己也发送一个SYN包(syn=k),即SYN+ACK包,此时服务器 进入SYN_RECV状态;
IP 192.168.1.123.7788 > 192.168.1.116.3337: S 1739326486:1739326486 ack 3626544837
IP 192.168.1.116.3337 > 192.168.1.123.7788: ack 1739326487,ack 1
一个三次握手的过程(图1,图2)

(图1)

(图2)
第一次握手的标志位(图3)
我们可以看到标志位里面只有个同步位,也就是在做请求(SYN)
(图3)
第二次握手的标志位(图4)
我们可以看到标志位里面有个确认位和同步位,也就是在做应答(SYN + ACK)
(图4)
第三次握手的标志位(图5)
我们可以看到标志位里面只有个确认位,也就是再做再次确认(ACK)
(图5)
大家很明白TCP初始化连接三次握手吧:发SYN包,然后返回SYN/ACK包,再发ACK包,连接正式建立。但是这里有点出入,当请求者收到SYS /ACK包后,就开始建立连接了,而被请求者第三次握手结束后才建立连接。
但是大家明白关闭连接的工作原理吗?
关闭连接要四次握手:发FIN包,ACK 包,FIN包,ACK包,四次握手!!
为什么呢,因为TCP连接是全双工,我关了你的连接,并不等于你关了我的连接。
客户端TCP状态迁移:
CLOSED->SYN_SENT->ESTABLISHED->FIN_WAIT_1->FIN_WAIT_2->TIME_WAIT->CLOSED
服务器TCP状态迁移:
CLOSED->LISTEN->SYN_RECEIVED->ESTABLISHED->CLOSE_WAIT->LAST_ACK->CLOSED
当客户端开始连接时,服务器还处于LISTENING,客户端发一个SYN包后,他就处于SYN_SENT状态,服务器就处于SYS收到状态,然后互相确认进入连接状态ESTABLISHED.
当客户端请求关闭连接时,客户端发送一个FIN包后,客户端就进入FIN_WAIT_1状态,等待对方的确认包,服务器发送一个ACK包给客户,客户端收到ACK包后结束FIN_WAIT_1状态,进入FIN_WAIT_2状态,等待服务器发过来的关闭请求,服务器发一个FIN包后,进入 CLOSE_WAIT状态,当客户端收到服务器的FIN包,FIN_WAIT_2状态就结束,然后给服务器端的FIN包给以一个确认包,客户端这时进入 TIME_WAIT,当服务器收到确认包后,CLOSE_WAIT状态结束了,这时候服务器端真正的关闭了连接.但是客户端还在TIME_WAIT状态下,什么时候结束呢.我在这里再讲到一个新名词:2MSL等待状态,其实TIME_WAIT就是2MSL等待状态,为什么要设置这个状态,原因是有足够的时间让ACK包到达服务器端,如果服务器端没收到ACK包,超时了,然后重新发一个FIN包,直到服务器收到ACK包,TIME_WAIT状态等待时间是在TCP重新启动后不连接任何请求的两倍。
大家有没有发现一个问题:如果对方在第三次握手的时候出问题,如发FIN包的时候,不知道什么原因丢了这个包,然而这边一直处在FIN_WAIT_2状态,而且TCP/IP并没有设置这个状态的过期时间,那他一直会保留这个状态下去,越来越多的FIN_WAIT_2状态会导致系统崩溃。
上面我碰到的这个问题主要因为TCP的结束流程未走完,造成连接未释放。现设客户端主动断开连接,流程如下
如上图所示,
Client 消息 Server
close()
------ FIN ------->
FIN_WAIT1 CLOSE_WAIT(server)
<----- ACK -------
FIN_WAIT2
close()(server)
<------ FIN ------
TIME_WAIT LAST_ACK(server)
------ ACK ------->
CLOSED(server)
CLOSED(client)
由于Server的Socket在客户端已经关闭时而没有调用关闭,造成服务器端的连接处在“挂起”状态,而客户端则处在等待应答的状态上。
此问题的典型特征是:一端处于FIN_WAIT2 ,而另一端处于CLOSE_WAIT。不过,根本问题还是程序写的不好,有待提高
-------------------------------------------------------------------------
CLOSE_WAIT,TCP的癌症,TCP的朋友。
CLOSE_WAIT状态的生成原因
首先我们知道,如果我们的服务器程序APACHE处于CLOSE_WAIT状态的话,说明套接字是被动关闭的!
因为如果是CLIENT端主动断掉当前连接的话,那么双方关闭这个TCP连接共需要四个packet:
Client ---> FIN ---> Server
Client <--- ACK <--- Server
这时候Client端处于FIN_WAIT_2状态;而Server 程序处于CLOSE_WAIT状态。
Client <--- FIN <--- Server
这时Server 发送FIN给Client,Server 就置为LAST_ACK状态。
Client ---> ACK ---> Server
Client回应了ACK,那么Server 的套接字才会真正置为CLOSED状态。
Server 程序处于CLOSE_WAIT状态,而不是LAST_ACK状态,说明还没有发FIN给Client,那么可能是在关闭连接之前还有许多数据要发送或者其他事要做,导致没有发这个FIN packet。
通常来说,一个CLOSE_WAIT会维持至少2个小时的时间。如果有个流氓特地写了个程序,给你造成一堆的CLOSE_WAIT,消耗
你的资源,那么通常是等不到释放那一刻,系统就已经解决崩溃了。
只能通过修改一下TCP/IP的参数,来缩短这个时间:修改tcp_keepalive_*系列参数有助于解决这个问题。
连接进程是通过一系列状态表示的,这些状态有:
LISTEN,SYN-SENT,SYN-RECEIVED,ESTABLISHED,FIN-WAIT-1,FIN-WAIT-2,CLOSE-WAIT,CLOSING,LAST-ACK,TIME-WAIT 和 CLOSED。
各个状态的意义如下:
CLOSED: 初始状态,表示TCP连接是“关闭着的”或“未打开的”。
3、关闭TCP连接一定需要4次挥手吗?
c不一定,4次挥手关闭TCP连接是最安全的做法。但在有些时候,我们不喜欢TIME_WAIT状态(如当MSL数值设置过大导致服务器端有太多TIME_WAIT状态的TCP连接,减少这些条目数可以更快地关闭连接,为新连接释放更多资源),这时我们可以通过设置SOCKET变量的SO_LINGER标志来避免SOCKET在close()之后进入TIME_WAIT状态,这时将通过发送RST强制终止TCP连接(取代正常的TCP四次握手的终止方式)。但这并不是一个很好的主意,TIME_WAIT 对于我们来说往往是有利的。
参考:http://justim.blog.51cto.com/740099/237548 和
http://hi.baidu.com/suxinpingtao51/item/be5f71b3a907dbef4ec7fd0e
TCP协议握手与分手的更多相关文章
- 对TCP协议握手的理解(转)
reference:https://www.cnblogs.com/awkflf11/p/9191708.html 目录: 31.Tcp握手的一些问题? 21.Tcp三次握手及SYN攻击: 四次握手? ...
- 关于TCP协议握手的那些事儿
旁白 今天面了下鹅场的后台技术开发,面试官问了我关于TCP连接协议的3次握手和断开连接协议的4次握手的问题.因为之前看过TCP的连接和断开处理,但是印象没有那么深刻.我想主要原因是一直重复简单的记忆, ...
- TCP协议的三次握手和四次分手
HTTP连接 HTTP协议即超文本传送协议(Hypertext Transfer Protocol ),是Web联网的基础,也是手机联网常用的协议之一,HTTP协议是建立在TCP协议之上的一种应用. ...
- 通俗大白话来理解TCP协议的三次握手和四次分手
通俗理解: 但是为什么一定要进行三次握手来保证连接是双工的呢,一次不行么?两次不行么?我们举一个现实生活中两个人进行语言沟通的例子来模拟三次握手. 引用网上的一些通俗易懂的例子,虽然不太正确,后面会指 ...
- 简析TCP的三次握手与四次分手(TCP协议头部的格式,数据从应用层发下来,会在每一层都会加上头部信息,进行封装,然后再发送到数据接收端)good
2014-10-30 分类:理论基础 / 网络开发 阅读(4127) 评论(29) TCP是什么? 具体的关于TCP是什么,我不打算详细的说了:当你看到这篇文章时,我想你也知道TCP的概念了,想要更 ...
- 通俗大白话来理解TCP协议的三次握手和四次断开
from : https://blog.csdn.net/Neo233/article/details/72866230?locationNum=15&fps=1%20HTTP%E6%8F%A ...
- http协议tcp协议ip协议三次握手四次挥手,为什么三次握手,为什么四次挥手,sockete套接字理解
1.1 TCP是什么? TCP是Tranfer Control Protocol的简称,TCP协议是一种面向连接的.可靠的.基于字节流的运输层通信协议.通过TCP协议传输,得到的是一个顺序的无差错的数 ...
- Tcp协议三次握手四次挥手
一.什么是TCP TCP(Transmission Control Protocol 传输控制协议)是一种面向连接(连接导向)的.可靠的. 基于IP的传输层协议.TCP在IP报文的协议号是6. 二.什 ...
- TCP协议的“三次握手”和“四次挥手”
TCP是面向连接的,无论哪一方向另一方发送数据之前,都必须先在双方之间建立一条连接.在TCP/IP协议中,TCP 协议提供可靠的连接服务,连接是通过三次握手进行初始化的.三次握手的目的是同步连接双方的 ...
随机推荐
- The Doors - POJ 1556 (线段相交)
题目大意:有一个房间(左上角(0,10),右下角(10,0)),然后房间里有N面墙,每面墙上都有两个门,求出来从初始点(0,5),到达终点(10,5)的最短距离. 分析:很明显根据两点之间直线最短 ...
- 敏捷开发松结对编程系列:L型代码结构案例StatusFiltersDropdownList(中)
这是松结对编程的第22篇(专栏目录). 接前文 业务代码 比较长,基本上就是看被注释隔开的三大段,先显示状态群筛选链接,然后是单个状态筛选,然后是显示下拉框的当前选中项,最后显示下拉框. public ...
- 学习了几天的jQuery Mobile的一点感受
一.Write less Do more! 这好像就是jQuery Mobile的口号吧.基于jQuery类库的jQuery Mobile移动web插件,有了这个轻量级插件后,排版方便了许多,很多样 ...
- 机房收费系统个人重构关于SQLHelper
近期在敲机房,对于SQLHelper也是心里有些怵,由于原来没用过,可是看了一些博客和资料后发现,假设不用这个类,会大大添加代码量,并且,事实上它并不新,它是一个有多个关于数据库增删改查操作的语句函数 ...
- The Six Types of Rails Association
翻译整理自:http://guides.rubyonrails.org/v3.2.13/association_basics.html 想吐槽一句,http://guides.ruby-china.o ...
- zedboard--交叉编译Opencv库的生成 分类: shell ubuntu fool_tree的笔记本 ZedBoard OpenCV 2014-11-08 18:57 171人阅读 评论(0) 收藏
Opencv的移植,xzyfeixiang和rainysky的博客. 第一步肯定是下载opencv的源码包 第二步已经做好的交叉编译环境. 第三步下载安装cmake apt-get install ...
- 《Linux Device Drivers》第十章 中断处理——note
概述:系统要及时的感知硬件的状态,通常有两种方式:一种是轮询.一种是通过响应硬件中断.前者会浪费处理器的时间,而后者不会. 准备并口 在没有节设定产生中断之前,并口是不会产生中断的 并口的标准规定设置 ...
- [转] npm命令概述
PS:问题,nvm找不到正确的下载server NVM_NODEJS_ORG_MIRROR=http://nodejs.org/dist nvm ls-remote NVM_NODEJS_ORG_MI ...
- Linux Increase The Maximum Number Of Open Files / File Descriptors (FD)
How do I increase the maximum number of open files under CentOS Linux? How do I open more file descr ...
- mvc form
当点击提交按钮后,想在Controll里取到Form里的数据. 必须在控件上设置name属性 例如<input type='text',name='userId'/>, 在controll ...