TCP协议之三次握手与四次挥手
TCP协议是TCP/IP体系中核心一个协议,该协议比起IP协议,ICMP协议,UDP协议都更复杂,因此这篇文章主要分析TCP协议在建立连接和断开连接的时候,状态转移以及报文段的内容。
下面,先放一张TCP的状态转移图:

TCP协议之三次握手
三次握手的过程是TCP在客户端和服务端建立连接的过程。简单的来说三次握手过程,就是客户端先发送一个连接请求给服务端,这是第一次握手。服务端接收到客户端发来的链接请求,然后在将确认的消息发给客户端,这是第二次握手。客户端对服务端发来的确认消息进行确认,然后将确认的消息发给服务端,这就是三次握手。三次握手之后,链接建立。
为什么一定是三次握手才能建立一个可靠地链接?如果不是三次握手,那么在客户端发送了链接请求之后,服务端对这个请求进行确认,就认定这次的链接已经成功建立,俗称的二次握手。这样的方式的弊端在哪里?
考虑这么一种情况,当客户端进行第一次握手时,发送了一个报文段,但是这个报文段因为网络的问题,迟迟没有到,这时,客户端又会再一次发送一个连接请求的报文段给服务端,这次成功接收,两者建立连接,并通信结束,关闭连接。这之后,因为网络延迟的那个报文段传到了服务端那里,服务端又以为客户端要建立新的连接,于是就同意了,向客户端发送确认。因为是二次握手,所以服务端后续要做的事情,就是等待客户端发送的消息,但是客户端是不会理会服务端传来的确认,所以服务端就会一直在等待客户端的数据,白白浪费了资源。
抓包分析TCP三次握手的报文段
现在,详细说一下三次握手具体是做了什么。
第一次握手,客户端发送一个报文段给服务端,该报文段中标志有SYN标志,该标志表示建立连接,以及一个初始的序列号。
第二次握手时,服务端发送一个报文段给客户端,该报文段中标志有SYN标志,和ACK标志。ACK标志的值是客户端发来的初始序号值+ 1,表示对客户端进行确认,报文段中还有服务端自己的初始序号。
第三次握手时,客户端发送一个报文段给服务端,该报文段中标志只有ACK标志,该ACK值是服务端的初始序列化的值 + 1,表示对服务端进行确认,以及还有一个序号值,该序号值为客户端第一次握手时的序号值 + 1。
三次握手建立连接结束。

图片上共有三行,每一行代表一次握手。我们先看第一行

可以看出,第一次握手时55732端口的程序主动发送一个建立链接的报文段给8888端口。这个55732端口是Java程序写的一个Socket客户端,8888端口是Socket程序写的服务端。建立连接的报文段,Flags中,只有SYN是为1的,这表明这是一个建立连接的报文段,该报文段中初始的序列号为0,ACK的number也为0。

第二次握手,是服务端发送给客户端一个报文段,表示确认收到了客户端的链接请求。该报文段中标志位有两个一个是ACK,一个SYN。表示收到链接请求,端口开放。该报文段中也会发送一个服务端自己的初始序列号。注意,这里ACK的值变成了1,是客户端初始序列号 + 1才有的。

第三次握手,是客户端发送给服务端一个报文段,表示确认收到了服务端的确认。因为双方端口都已经打开,所以客户端在发,就不会再有SYN标志了,这里只有ACK标志,该标志的值也是1,是因为服务端的初始序列号 + 1造成的。这里的序列号为1,是因为第一次握手,发送了一个SYN标志,该标志会占用1个序号值,但是ACK不会。
对应到上面的状态图中,就是客户端是主动打开,从起始点发送SYN报文段,进入SYN_SENT状态,然后接受SYN,ACK,走黑粗线的路径进入到数据传输状态,也就是ESTABLISHED,对于服务端而言,就是从起始点走虚线的部分,被动打开后,接受客户端的SYN,进入SYN_RCVD,最后,接受客户端第三次握手的ACK,进入数据传输状态,也就是ESTABLISHED。
TCP协议之四次挥手
TCP协议是一种全双工协议,拥有半关闭的特性。
全双工的意思是A可以往B发送数据,B同时也可以给A发送数据。
半双工的意思是A可以往B发送数据,B也可以给A发送数据,但是两者不能同时。
单工的意思是只能A给B发送数据,或者B给A发送数据。
半关闭的意思是将全双工,变成单工,也就是如果B关闭,是指B不能给A发数据了,但是A可以给B发
所以TCP协议如果要正常的关闭客户端与服务端的链接,需要四次报文段,也就是4次挥手。
首先,客户端因为应用程序的执行完毕,会主动开始断开链接,这时会发送一个含有FIN标志位的报文段。这表明客户端不会再发送数据给服务端。这时第一次挥手。
然后,服务端接收到这个报文段,就会发送一个含有ACK标志的报文段给客户端,表示确认收到了关闭的报文段。这是第二次挥手。
然后,服务端在处理完服务端的事情后,也会发送一个含有FIN的报文段给客户端,表示服务端不会再发送数据给客户端。这是第三次挥手。
最后,客户端收到这个报文段后,就会发送一个含有ACK的报文段给服务端,表示确认收到了关闭的报文段。这是第四次挥手。至此,链接全部关闭。
抓包分析TCP四次挥手的报文段

不用看黑色报文,4行代表关闭的4次挥手的过程,每一行是一次挥手。
第一行,是客户端主动关闭链接,发送一个含有FIN的报文段,这是第一次挥手
第二行,是服务端确认客户端的FIN报文,发送一个ACK的确认报文,该ACK的值是9,而第一行的序列号的8,因为与SYN一样,FIN也占一个序列号。
忽略黑的后第三行,服务端发送一个含有FIN的报文段,这是第三次挥手。
第四行,客户端会这个FIN报文段进行确认,发送了一个ACK报文段。该ACK的值是第三行的序列号 + 1。
对应到上面的状态图中,先说服务端的状态转移,因为收到了客户端的FIN,所以发送一个ACK给客户端,同时自己进入到CLOSE_WAIT状态,等待服务端应用程序结束,发送FIN给客户端,自己进入LAST_ACK状态,等待最后的ACK到来,接收到ACK,结束状态。
客户端因为先发起关闭,状态比较复杂,他先发送一个FIN给服务端,自己进入了FIN_WAIT_1状态,这时他等待接收服务端的报文,该报文会有三种可能:
- 只有服务端的ACK
- 只有服务端的FIN
- 基于服务端的ACK,又有FIN
对于第一种,该ACK是服务端确认了客户端的FIN而发的,这时客户端会进入FIN_WAIT_2状态,这是当他收到服务端的FIN来时,发送了一个ACK,会进入到TIME_WAIT状态,他要在这个状态等待2MSL的时间,1个MSL是报文段在网络的最长时间,客户端等待2MSL,是为了当最后一个ACK丢失时,可以在发送一次,因为这时,服务端在等待超时后在发送一个FIN给客户端,所以客户端也知道了ACK丢失了。
对于第二种,只有服务端的FIN的时,会发送一个ACK给服务端,客户端进入CLOSING状态,然后接收到服务端的ACK时,也会进入TIME_WAIT状态。
对于第三种,同时都收到了,就省略了进入CLOSING状态,直接进入TIME_WAIT状态。抓包分析的截图,就是这种情况。
TCP协议之三次握手与四次挥手的更多相关文章
- TCP协议三次握手与四次挥手通俗解析
TCP/IP协议三次握手与四次握手流程解析 一.TCP报文格式 TCP/IP协议的详细信息参看<TCP/IP协议详解>三卷本.下面是TCP报文格式图: 图1 TCP报文格式 上图中有几个字 ...
- TCP协议三次握手与四次挥手详解
在计算机网络的学习中TCPi协议与Http协议是我们必须掌握的内容,其中Tcp协议属于传输层,而Http协议属于应用层,本博客主要讲解Tcp协议中的三次握手与四次挥手,关于Http协议感兴趣的可以参看 ...
- TCP协议三次握手和四次挥手
http://www.cnblogs.com/rootq/articles/1377355.html TCP(Transmission Control Protocol) 传输控制协议 TCP是主机对 ...
- TCP/IP之三次握手、四次挥手
参照:http://www.cnblogs.com/hnrainll/archive/2011/10/14/2212415.html 在TCP/IP协议中,TCP协议提供可靠的连接服务,采用三次握手建 ...
- TCP协议三次握手、四次挥手
TCP的概述 TCP 把连接作为最基本的对象,每一条 TCP 连接都有两个端点,这种断点我们叫作套接字(socket),它的定义为端口号拼接到 IP 地址即构成了套接字,例如,若 IP 地址为 192 ...
- TCP协议三次握手、四次挥手过程
本文通过图来梳理TCP-IP协议相关知识.TCP通信过程包括三个步骤:建立TCP连接通道,传输数据,断开TCP连接通道.如图1所示,给出了TCP通信过程的示意图. 上图主要包括三部分:建立连接.传输数 ...
- TCP协议“三次握手”与“四次挥手”详解(下)
前面进行“三次握手”建立连接后,当客户端的数据发送完毕,它就会要求与服务器端断开连接,那么就要进行“四次挥手”进行连接的释放. 注意,此处所谓的“客户端”与“服务器端”,只是为了方便标识连接的双方,即 ...
- TCP协议“三次握手”与“四次挥手”详解(上)
在使用TCP协议进行数据的传输之前,客户端与服务器端需要建立TCP Connection,即建立连接,之后两端才能进行数据的传输. 下面堆TCP连接“三次握手”的过程进行说明. 1.相关概念 首先,我 ...
- TCP/IP协议三次握手和四次挥手大白话解说
前言 昨天晚上被一位师傅问到了TCP/IP的工作机制,心里很清楚三次握手,然而对于四次挥手却忘了,这是大学习里学过的,奋而翻阅书籍和网络对之前所学的做一个温顾,算是夯实自我吧. TCP(Transmi ...
随机推荐
- CardboardSDK-iOS 源码简单分析
该项目地址: 地址 克隆地址为 https://github.com/rsanchezsaez/CardboardSDK-iOS.git 目前如果想在iOS设备上实现双目VR的功能,Google 已经 ...
- canvas动态小球重叠效果
前面的话 在javascript运动系列中,详细介绍了各种运动,其中就包括碰壁运动.但是,如果用canvas去实现,却是另一种思路.本文将详细介绍canvas动态小球重叠效果 效果展示 静态小球 首先 ...
- react+redux构建淘票票首页
react+redux构建淘票票首页 描述 在之前的项目中都是单纯的用react,并没有结合redux.对于中小项目仅仅使用react是可以的:但当项目变得更加复杂,仅仅使用react是远远不够的,我 ...
- 前端开发在IOS端遇到的一个诡异问题(Delegate 失效)
一.前言 最近同事问到一个问题,一个前端页面在IOS端真机测试下出现一个比较诡异的问题,如果没有遇到过估计也是一筹莫展.今天特此记录一下,或许能帮到后面遇到这个问题的朋友少绕一些弯路.这是关于JQue ...
- java中File类的常用所有方法及其应用
创建:createNewFile()在指定位置创建一个空文件,成功就返回true,如果已存在就不创建,然后返回false.mkdir() 在指定位置创建一个单级文件夹.mkdirs() 在指定位置 ...
- C#数组和集合
一维数组 概述:数组是通过指定数组的元素类型.数组的(秩)维数及数组每个维度上的上限和下限来定义的,及一个数组的定义需要包含以下几个要素. 类型 数组的维数 每个维的上限下限 声明:数据类型 ...
- WebSockets介绍
Web sockets定义为在servers和clients之间的双向连接.意味着servers和clients可以同时交流并发送数据.这种协议是从底层就是双工连接.Web sockets技术上得到了 ...
- BZOJ 3083: 遥远的国度(树链剖分+DFS序)
可以很显而易见的看出,修改就是树链剖分,而询问就是在dfs出的线段树里查询最小值,但由于这道题会修改根节点,所以在查询的时候需判断x是否为root的祖先,如果不是就直接做,是的话应该查询从1-st[y ...
- Qt中纯C++项目发布为dll的方法(超详细步骤)
众所周知,我们可以将C++项目中的类以及某些方法导出,形成 .dll 文件,以供其他程序使用,下面将说明Qt环境下的使用方法. 首先创建共享库,步骤如下: 下一步会出现类对话框等等,不用管它,直接点击 ...
- AngularJs ng-repeat指令中怎么实现含有自定义指令的动态html
今天用angular写table的时候,遇到了一个问题.在ng-repeat中,含有动态的html,而这些html中含有自定义指令. 因为希望实现一个能够复用的table,所以定义了一个指令mySta ...