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状态,这时他等待接收服务端的报文,该报文会有三种可能:

  1. 只有服务端的ACK
  2. 只有服务端的FIN
  3. 基于服务端的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协议之三次握手与四次挥手的更多相关文章

  1. TCP协议三次握手与四次挥手通俗解析

    TCP/IP协议三次握手与四次握手流程解析 一.TCP报文格式 TCP/IP协议的详细信息参看<TCP/IP协议详解>三卷本.下面是TCP报文格式图: 图1 TCP报文格式 上图中有几个字 ...

  2. TCP协议三次握手与四次挥手详解

    在计算机网络的学习中TCPi协议与Http协议是我们必须掌握的内容,其中Tcp协议属于传输层,而Http协议属于应用层,本博客主要讲解Tcp协议中的三次握手与四次挥手,关于Http协议感兴趣的可以参看 ...

  3. TCP协议三次握手和四次挥手

    http://www.cnblogs.com/rootq/articles/1377355.html TCP(Transmission Control Protocol) 传输控制协议 TCP是主机对 ...

  4. TCP/IP之三次握手、四次挥手

    参照:http://www.cnblogs.com/hnrainll/archive/2011/10/14/2212415.html 在TCP/IP协议中,TCP协议提供可靠的连接服务,采用三次握手建 ...

  5. TCP协议三次握手、四次挥手

    TCP的概述 TCP 把连接作为最基本的对象,每一条 TCP 连接都有两个端点,这种断点我们叫作套接字(socket),它的定义为端口号拼接到 IP 地址即构成了套接字,例如,若 IP 地址为 192 ...

  6. TCP协议三次握手、四次挥手过程

    本文通过图来梳理TCP-IP协议相关知识.TCP通信过程包括三个步骤:建立TCP连接通道,传输数据,断开TCP连接通道.如图1所示,给出了TCP通信过程的示意图. 上图主要包括三部分:建立连接.传输数 ...

  7. TCP协议“三次握手”与“四次挥手”详解(下)

    前面进行“三次握手”建立连接后,当客户端的数据发送完毕,它就会要求与服务器端断开连接,那么就要进行“四次挥手”进行连接的释放. 注意,此处所谓的“客户端”与“服务器端”,只是为了方便标识连接的双方,即 ...

  8. TCP协议“三次握手”与“四次挥手”详解(上)

    在使用TCP协议进行数据的传输之前,客户端与服务器端需要建立TCP Connection,即建立连接,之后两端才能进行数据的传输. 下面堆TCP连接“三次握手”的过程进行说明. 1.相关概念 首先,我 ...

  9. TCP/IP协议三次握手和四次挥手大白话解说

    前言 昨天晚上被一位师傅问到了TCP/IP的工作机制,心里很清楚三次握手,然而对于四次挥手却忘了,这是大学习里学过的,奋而翻阅书籍和网络对之前所学的做一个温顾,算是夯实自我吧. TCP(Transmi ...

随机推荐

  1. ActionMode 就记这么一点,不能更多了

    话说程序猿都是段子手,看到有的程序猿写文章,前面都会先写一个段子,我这么有幽默感的段子手,也决定效仿一下. "段子." 写完段子,下面开始进入正题. 今天要说的 ActionMod ...

  2. css3 3D效果

    css3 3D变形 transfrom初学 这个礼拜学了css3 3d,感觉到css无穷的魅力,可以通过几个特定的代码符号创建出3D效果的页面. ___ 透视 一个元素需要一个透视点才能激活3D空间, ...

  3. win8下 msvcr100d.dll文件缺失解决方法

    一.如果在运行某软件或编译程序时提示缺少.找不到msvcp100d.dll等类似提示,您可将从载来的msvcp100d.dll拷贝到指定目录即可(一般是system系统目录或放到软件同级目录里面),或 ...

  4. python 库安装笔记

    python 库安装笔记 zoerywzhou@163.com http://www.cnblogs.com/swje/ 作者:Zhouwan 2017-2-22 友情提示 安装python库的过程中 ...

  5. NSRunLoop原理详解——不再有盲点

    编程最怕的就是有盲点,不确定,而runloop官网对其提及的又很少:那么看完这篇应该使你有底气很多~ RunLoop整体介绍 An event-processing loop, during whic ...

  6. Java自动装箱和拆箱

    jdk5.0之后,在基本数据类型封装类之间增加了自动装箱和拆箱的功能,其实“自动”的实现很简单,只是将装箱和拆箱通过编译器,进行了“自动补全”,省去了开发者的手动操作. 而进行封装类与对应基本数据类型 ...

  7. JDBC链接mysql数据库

    Unit_1 首先:JDBC:java database connectivity SUN公司提供的一套操作数据库的标准规范. JDBC与数据库驱动的关系是接口与实现的关系. JDBC涉及到四个核心的 ...

  8. 线程协作方法sleep、yield、wait、join

      sleep(休眠)   当t线程调用Thread.sleep()时,会让线程t休眠指定时间   Thread.sleep() 和 Thread.currentThread().sleep() 效果 ...

  9. Spark集群搭建_Standalone

    2017年3月1日, 星期三 Spark集群搭建_Standalone Driver:    node1    Worker:  node2    Worker:  node3 1.下载安装 下载地址 ...

  10. 深入浅出Redis-Spring整合Redis

    概述: 在之前的博客中,有提到过Redis 在服务端的一些相关知识,今天主要讲一下Java 整合Redis的相关内容. 下面是Jedis 的相关依赖: <dependency> <g ...