http://blog.csdn.net/chenhanzhun/article/details/41622555

注:TCP 连接的建立和释放在网络协议中是比较重要的,由于本人理解也不是很透彻,欢迎各位批评指正。

前言

TCP 是面向连接的、可靠的字节流协议。因此,在传输数据之前通信双方必须建立一个 TCP 连接,建立 TCP 连接需要在服务器和客户端之间进行三次握手。通信双方数据传输完毕之后进行连接释放,释放连接需要在通信双方之间进行四次挥手。

TCP 状态机

TCP 所谓的“连接”,只是通信双方维护一个“连接状态”,让它看上去好像有连接一样,其实 TCP 连接是虚拟的连接,不是电路连接。首先看下 TCP 的状态机,状态机是 TCP 连接与释放的全过程。如下图所示:

下面针对 TCP 状态机所出现的各个状态进行简要的分析:

  • CLOSED:表示初始状态。对服务端和客户端双方都一样。
  • LISTEN:表示监听状态。服务端调用了 listen 函数使其处于监听状态,此时可以开始 accept (接收)客户端的连接。
  • SYN_SENT:表示客户端已经发送了 SYN 报文段,则会处于该状态。当客户端调用 connect 函数发起连接请求时,首先发 SYN 给服务端,然后自己进入 SYN_SENT 状态,并等待服务端发送 ACK+SYN 作为请求应答。
  • SYN_RCVD:表示服务端收到客户端发送 SYN 报文段。服务端收到这个报文段后,进入 SYN_RCVD 状态,然后发送 ACK+SYN 给客户端。
  • ESTABLISHED:表示 TCP 连接已经成功建立,通信双方可以开始传输数据。服务端发送完 ACK+SYN 并收到来自客户端的 ACK 后进入该状态,客户端收到来自服务器的 SYN+ACK 并发送 ACK 后也进入该状态。
  • FIN_WAIT_1:表示主动关闭连接。无论哪方调用 close 函数发送 FIN 报文都会进入这个这个状态。
  • FIN_WAIT_2:表示被动关闭方同意关闭连接。主动关闭连接方收到被动关闭方返回的 ACK 后,会进入该状态。
  • TIME_WAIT:表示收到对方的 FIN 报文并发送了 ACK 报文,就等 2MSL 后即可回到 CLOSED 状态了。如果 FIN_WAIT_1 状态下,收到对方同时带 FIN 标志和 ACK 标志的报文时,可以直接进入 TIME_WAIT 状态,而无须经过 FIN_WAIT_2 状态。
  • CLOSING:表示双方同时关闭连接。如果双方几乎同时调用 close 函数,那么会出现双方同时发送 FIN 报文的情况,就会出现 CLOSING 状态,表示双方都在关闭连接。
  • CLOSE_WAIT:表示被动关闭方等待关闭。当收到对方调用 close 函数发送的 FIN 报文时,回应对方 ACK 报文,此时进入 CLOSE_WAIT 状态。
  • LAST_ACK:表示被动关闭方发送 FIN 报文后,等待对方的 ACK 报文状态,当收到 ACK 后进入CLOSED状态。

TCP 连接的建立

TCP 连接的正常建立过程通信双方需要三次握手,其过程如下图所示:

TCP 协议提供可靠的连接服务,采用有保障的三次握手方式来创建一个 TCP 连接。三次握手的具体过程如下:

  1. 客户端进程向服务端发出连接请求,请求报文的报文段首部中的控制位标志 SYN=1(有关 TCP 控制位信息参考《TCP 协议》),由于是首次请求建立连接,因此,控制位标志 ACK=0,该报文段包含计算机随机生成的初始序号 seq=x。发送请求连接的 TCP 报文段,此时客户端进程进入 SYN_SENT 状态,这是 TCP 连接的第一次握手。
  2. 服务端收到客户端发来的请求报文后,若同意建立连接,则向客户端发送确认。确认报文中的控制位 SYN=1,ACK=1,确认应答号 ack=x+1(即在接收到序列号值基础上加 1 ),并且发送自己的一个初始序列号 seq=y(即请求与客户端连接)。此时,服务端进入SYN_RCVD状态,这是TCP连接的第二次握手。
  3. 客户端进程收到服务端进程的确认报文后,还要向服务端发出确认信息。确认报文段的控制位 ACK=1,确认应答号 ack=y+1(即在接收到序列号值基础上加 1 ),此时,客户端进入 ESTABLISHED 状态。服务器收到来自客户端的确认应答信息也进入  ESTABLISHED 状态。这是TCP连接的第三次握手。此时,TCP 连接成功建立。

同时打开连接请求

正常情况下,通信一方请求建立连接,另一方响应该请求,但是如果出现,通信双方同时请求建立连接时,则连接建立过程并不是三次握手过程,而且这种情况的连接也只有一条,并不会建立两条连接。同时打开连接时,两边几乎同时发送 SYN,并进入 SYN_SENT 状态,当每一端收到 SYN 时,状态变为 SYN_RCVD,同时双方都再发 SYN 和 ACK 作为对收到的 SYN 进行确认应答。当双方都收到 SYN 及相应的 ACK 时,状态变为 ESTABLISHED。其过程入下:

TCP 连接释放

由于 TCP 连接是全双工的,因此每个方向都必须单独进行关闭。原则是主动关闭的一方发送一个 FIN 报文来表示终止这个方向的连接,收到一个 FIN 意味着这个方向不再有数据流动,但另一个方向仍能继续发送数据,直到另一个方向也发送 FIN 报文。TCP 连接释放的过程如下图所示:

以下是释放连接的四次挥手过程:

  1. 客户端进程主动向服务端发出连接释放请求报文段,并停止发送数据,主动关闭 TCP 连接。释放连接报文段中控制位 FIN=1,序列号为 seq=i,发送该报文段之后客户端进入FIN_WAIT_1(终止等待1)状态,等待服务器的确认。这是 TCP 连接释放的第一次挥手。
  2. 服务器收到连接释放请求报文段后即发出确认释放连接的报文段,该报文段中控制位 ACK=1,确认应答号为 ack=i+1,然后服务器进入CLOSE_WAIT(关闭等待)状态。此时 TCP 处于半关闭状态,即客户端已经不向服务器发送数据,但服务器仍可向客户端发送数据。这是TCP连接释放的第二次挥手。
  3. 客户端收到服务器的确认信息后,就进入了FIN_WAIT_2(终止等待2)状态,等待服务器发出连接释放请求报文段,若没有数据需要传输,服务器被动向客户端发出链接释放请求报文段中,报文段中控制位 FIN=1,序列号 seq=j,此时服务器进入LAST_ACK(最后确认)状态,等待客户端的确认应答。这是 TCP 连接释放的第三次挥手。
  4. 客户端收到服务器的连接释放请求后,必须对此发出确认。确认报文段中控制位 ACK=1,确认应答号 ack=j+1,客户端发出确认应答信息之后后进入TIME_WAIT(时间等待)状态。在这段时间内 TCP连接并没有释放,必须等待 2MSL 时间后,客户端才进入 CLOSED 状态。服务器收到了客户端的确认应答后,就进入了 CLOSED 状态。直到客户端和服务器都进入 CLOSED 状态后,连接就完全释放了,这是TCP连接释放的第四次挥手。

同时关闭连接

正常情况下,通信一方请求连接关闭,另一方响应连接关闭请求,并且被动关闭连接。但是若出现同时关闭连接请求时,通信双方均从 ESTABLISHED 状态转换为 FIN_WAIT_1 状态。任意一方收到对方发来的 FIN 报文段后,其状态均由 FIN_WAIT_1转变到 CLOSING 状态,并发送最后的 ACK 数据段。当收到最后的 ACK 数据段后,状态转变化 TIME_WAIT,在等待 2MSL 时间后进入到 CLOSED 状态,最终释放整个 TCP 传输连接。其过程入下:

TCP 相关疑问

为什么在 TCP 协议里,建立连接是三次握手,而关闭连接却是四次握手?

因为当处于 LISTEN 状态的服务器端收到来自客户端的 SYN 报文(客户端希望新建一个TCP连接)时,它可以把 ACK (确认应答)和 SYN (同步序号)放在同一个报文里来发送给客户端。但在关闭 TCP 连接时,当收到对方的 FIN 报文时,对方仅仅表示对方已经没有数据发送给你了,但是你自己可能还有数据需要发送给对方,则等你发送完剩余的数据给对方之后,再发送 FIN 报文给对方来表示你数据已经发送完毕,并请求关闭连接,所以通常情况下,这里的 ACK 报文和 FIN 报文都是分开发送的。

为什么一定要进行三次握手?
        当客户端向服务器端发送一个连接请求时,由于某种原因长时间驻留在网络节点中,无法达到服务器端,由于 TCP 的超时重传机制,当客户端在特定的时间内没有收到服务器端的确认应答信息,则会重新向服务器端发送连接请求,且该链接请求得到服务器端的响应并正常建立连接,进而传输数据,当数据传输完毕,并释放了此次 TCP 连接。若此时第一次发送的连接请求报文段延迟了一段时间后,到达了服务器端,本来这是一个早已失效的报文段,但是服务器端收到该链接请求后误以为客户端又发出了一次新的连接请求,于是服务器端向客户端发出确认应答报文段,并同意建立连接。如果没有采用三次握手建立连接,由于服务器端发送了确认应答信息,则表示新的连接已成功建立,但是客户端此时并没有向服务器端发出任何连接请求,因此客户端忽略服务器端的确认应答报文,更不会向服务器端传输数据。而服务器端却认为新的连接已经建立了,并在一直等待客户端发送数据,这样服务器端一直处于等待接收数据,直到超出计数器的设定值,则认为客户端出现异常,并且关闭这个连接。在这个等待的过程中,浪费服务器的资源。如果采用三次握手,客户端就不会向服务端发出确认应答信息,服务器端由于没有收到客户端的确认应答信息,从而判定客户端并没有请求建立连接,从而不建立该连接。

为什么需要在 TIME_WAIT 状态必须等待 2MSL 时间,而不直接给进入 CLOSED 状态?

主要有两个原因:

  1. TIME_WAIT 确保有足够的时间让对端收到了ACK,如果被动关闭的那方没有收到 ACK,就会触发被动端重发 FIN。因为最后一次确认应答 ACK 报文段很有可能丢失,因而使被动关闭方处于在LIST_ACK 状态的,此时被动关闭方会重发这个 FIN+ACK 报文段,在这等待的 2MSL 时间内主动关闭方重新收到这个被动关闭方重发的 FIN+ACK 报文段,因此,主动关闭方会重新发送确认应答信息,从而重新启动 2MSL 计时器,直到通信双方都进入 CLOSED 状态。如果主动关闭方在 TIME_WAIT 状态不等待一段时间就直接释放连接并进入 CLOSED 状态,那么主动关闭方无法收到来自被动关闭方重发的 FIN+ACK 报文段,也就不会再发送一次确认 ACK 报文段,因此被动关闭方就无法正常进入CLOSED 状态。
  2. 有足够的时间让这个连接不会跟后面的连接混在一起。防止已失效的请求连接出现在本连接中。在连接处于 2MSL 等待时,任何迟到的报文段将被丢弃,因为处于 2MSL等待的、由该插口(插口是IP和端口对的意思,socket)定义的连接在这段时间内将不能被再用,这样就可以使下一个新的连接中不会出现这种旧的连接之前延迟的报文段。

参考资料:

《TCP/IP 详解》

《TCP连接的建立和释放》

《TCP/IP状态变迁图和TCP三次握手与四次挥手》

《TCP 的那些事儿》

TCP/IP详解之 《网络协议》图解 TCP 连接建立与释放相关推荐

  1. 《TCP/IP详解:卷1》之TCP/UDP总结

    对于<TCP/IP详解:卷1>这本书来说也算是我的老朋友了,在之前做协议分析项目时曾经系统的看过,在之后开发网络库,做入侵检测时也时常翻阅,但是对书中内容的记忆却比较混乱,也常常忘记一些重 ...

  2. 《TCP/IP详解卷一:协议》 概述

    分层 TCP/IP协议族是一组不同层次上的多个协议的组合.TCP/IP通常被认为是一个四层次协议系统. 链路层(数据链路层或网络接口层):通常包括操作系统中的设备驱动程序和计算机中对应的网络接口卡.用 ...

  3. 『TCP/IP详解——卷一:协议』读书笔记——03

    2013-08-17 17:31:49 1.7 分用 分用(Demultiplexing):这是一个过程--当目的主机收到一个以太网数据帧时,数据就开始从协议栈中由底向上升,同时去掉各层协议上的报文首 ...

  4. 【TCP/IP详解 卷一:协议】第十八章 TCP连接 的建立与终止 (2)其余内容

    18.5 TCP的半关闭 牢记 TCP 是 全双工 的. 半关闭:TCP提供了连接的一端 在结束了它的发送后 还能接收来自另外一端数据的能力.但是只有很少的应用程序利用它. 为了实现这个特性,编程接口 ...

  5. 【TCP/IP详解 卷一:协议】第十九章 TCP的交互数据流

    19.1 引言 前一章我们介绍了TCP连接的建立与释放:三握四挥,以及状态转移图. TCP报文段分为:交互数据,以及成块数据(下一章介绍). 交互数据:例如telnet,ssh,这种类型的协议在大多数 ...

  6. 【TCP/IP详解 卷一:协议】第十二章 广播和多播

    建议参考:广播和多播 IGMP 12.1 引言 IP地址知识点回顾: IP地址分为三种:(1)单播地址 (2)广播地址 (3)多播地址 另外一种是,IP地址一般划分成五类:A-E类. 单播 考虑 类似 ...

  7. TCP/IP详解 卷1:协议 学习笔记 第十六章 BOOTP:引导程序协议

    一个无盘系统在不知道自身IP地址情况下,进行系统引导时能通过RARP协议获取它的IP地址,使用RARP会有两个问题:(1)IP地址是返回的唯一结果:(2)RARP使用链路层广播,RARP请求不会被路由 ...

  8. 《TCP/IP详解·卷1:协议》随笔(已完结)

    第一章.概述 Internet的成功 Internet体系结构被设计成支持现有网络互联,同时提供了广泛的服务与协议操作. 选用数据包的分组交换主要是因为它的鲁棒性与效率,而相对来说数据安全性与交付可预 ...

  9. TCP/IP详解卷1 - wireshark抓包分析

    TCP/IP详解卷1 - 系列文 TCP/IP详解卷1 - 思维导图(1) TCP/IP详解卷1 - wireshark抓包分析 引言 在初学TCP/IP协议时,会觉得协议是一种很抽象的东西,通过wi ...

  10. 《TCP/IP详解》中文版下载地址

    <TCP/IP详解>中文版下载地址 TCP/IP详解 卷1协议http://www.chinaccna.com/Soft/ShowSoft.asp?SoftID=822 TCP/IP详解 ...

最新文章

  1. 微信小程序导航栏设置透明
  2. 在Linux下怎样让top命令启动之后就按内存使用排序(或CPU使用排序)?
  3. java.security.cet.CertPathValidatorException: Path does not chain with any of the trust anchors 解决办法
  4. 008 Spark中standalone模式的HA(了解,知道怎么配置即可)
  5. java set path_Java Path.setEffect方法代码示例
  6. GAN生成对抗网络-INFOGAN原理与基本实现-可解释的生成对抗网络-06
  7. pat 乙级 1030 完美数列(C++)
  8. python urllib模块学习笔记
  9. 【pytorch】torch.cat()函数
  10. python 可视化 画直线_用Python画江苏省地图,实现各地级市数据可视化
  11. expdp 简单例子
  12. python实现顺序查找和哈希查找算法
  13. 【李宏毅2020 ML/DL】P24 Semi-supervised
  14. VSTO/Excel: 获取Excel图表中的某个点的数据
  15. matlab实现QPSK调制解调
  16. 禁用或启用戴尔笔记本电脑上的触摸板
  17. threejs修改模型旋转轴
  18. 【已解决】VS code源代码控制器显示5k+的修改文件
  19. oracle 查看用户日志,Oracle查看用户操作sql语句以及数据库日志
  20. 数据分析之numpy基础/matplotlib绘图/numpy常用函数/杂项功能

热门文章

  1. glPushMatrix和glPopMatrix
  2. HDU 4022 Bombing(11年上海 二分)
  3. 想知道如何给游戏视频配音?有三个好方法教给你
  4. Android自定义ViewGroup第十二式之年年有鱼
  5. 计算机教师面试1分钟自我介绍视频,音乐教师面试1分钟自我介绍4篇
  6. 测试员老张发觉越努力越费劲,越加班时间却越不够用,只能陷入低效率的加班中,循环往复
  7. 2022.9.9 360笔试题-老张修路
  8. Android移动应用开发教程④
  9. 虚拟机中安装windows server 2003忘记密码
  10. testing....