1. TCP 之11种状态变迁

TCP 为一个连接定义了 11 种状态,并且 TCP 规则规定如何基于当前状态及在该状态下所接收的分节从一个状态转换到另一个状态。如,当某个应用进程在 CLOSED 状态下执行主动打开时,TCP 将发送一个 SYN,且新的状态是 SYN_SENT。如果这个 TCP 接着接收到一个带 ACK 的 SYN,它将发送一个 ACK,且新的状态是 ESTABLISHED。这个最终状态是绝大多数数据传送发送的状态。

自 ESTABLISHED 状态引出的两个箭头处理连接的终止。如果某个应用进程在接收到一个 FIN 之前调用 close(主动关闭),那就转换到 FIN_WAIT_1 状态。但如果某个应用进程在 ESTABLISHED 状态期间接收到一个 FIN(被动关闭),那就转换到 CLOSE_WAIT 状态。

TCP 的状态变迁图 1

1.1 观察分组

如下图示例中的客户通告一个值为 536 的 MSS(表示该客户只实现了最小重组缓冲区大小),服务通告一个值为 1460 的 MSS(以太网上 IPv4 的典型值)。不同方向上 MSS 值不相同不成问题。

TCP 连接的分组交换图 2



如上图,一旦建立一个连接,客户就构造一个请求并发送给服务器。这里假设该请求适合于单个 TCP 分节(即请求大小小于服务器通告的值为 1460 字节的 MSS)。服务器处理该请求并发送一个应答,同样假设该应答也适合于单个分节(本例即小于 536 字节)。如上图的粗箭头所示。注意,服务器对客户请求的确认是伴随其应答发送的。这种做法称为捎带(piggybacking),它通常在服务器处理请求并产生应答的时间少于 200ms 时发生。如果服务器耗用更长时间,譬如说 1s,那么我们将看到先是确认后是应答。

1.2 TIME_WAIT 状态

TIME_WAIT 状态也称为 2MSL 等待状态。每个具体 TCP 实现必须选择一个报文段最大生存时间 MSL(Maximum Segment Lifetime)。它是任何报文段被丢弃前在网络内的最长时间。这个时间是有限的,因为 TCP 报文段以 IP 数据报在网络内传输,而 IP 数据报则有限制其生存时间的 TTL 字段。

注:RFC 793[Postel 1981c] 指出 MSL 为 2 分钟。然而,实现中的常用值是 30 秒,1 分钟,或 2 分钟。

对一个具体实现所给定的 MSL 值,处理的原则是:当 TCP 执行一个主动关闭,并发回最后一个 ACK,该连接必须在 TIME_WAIT 状态停留的时间为 2 倍的 MSL。这样可让 TCP 再次发送最后的 ACK 以防这个 ACK 丢失(另一端超时并重发最后的 FIN)。

这种 2MSL 等待的另一个结果是这个 TCP 连接在 2MSL 等待期间,定义这个连接的 socket(客户的 IP 地址和端口号,服务器的 IP 地址和端口号)不能再被使用。这个连接只能在 2MSL 结束后才能再被使用。

大多数 TCP 实现(如伯克利版)强加了更加严格的限制。在 2MSL 等待期间,socket 中使用的本地端口在默认情况下不能再被使用。

某些实现和 API 提供了一种避开这个限制的方法。可使用 setsockopt API 对该套接字设置 SO_REUSEADDR 属性,该属性可让处于 2MSL 等待的本地端口再次被使用。

TIME_WAIT 状态有两个存在的理由:

  1. 可靠地实现 TCP 全双工连接的终止;
  2. 允许老的重复分节在网络中消逝。
第一个理由的解释:

如上图 2,假设最终的 ACK 丢失了,服务器将重新发送它的最终的那个 FIN,因此客户必须维护状态信息,以允许它重新发送最终那个 ACK。要是客户不维护状态信息,它将响应一个 RST(另外一种类型的 TCP 分节),该分节将被服务器解释成一个错误。如果 TCP 打算执行所有必要的工作以彻底终止某个连接上两个方向的数据流(即全双工关闭),那么它必须正确处理连接终止序列 4 个分节中任何一个分节丢失的情况。本例也说明为什么执行主动关闭的那一端是处于 TIME_WAIT 状态的那一端:因为可能不得不重传最终那个 ACK 的就是那一端。

第二个理由的解释:

假设在 12.106.32.254 的 1500 端口和 206.168.112.219 的 21 端口之间有一个 TCP 连接。我们关闭这个连接,过一段时间后在相同的 IP 地址和端口之间建立另一个连接。后一个连接称为前一个连接的化身,因为它们的 IP 地址和端口号都相同。TCP 必须防止来自某个连接的老的重复分组在该连接已终止后再现,从而被误解成属于同一个连接的某个新的化身。为做到这一点,TCP 将不给处于 TIME_WAIT 状态的连接发起新的化身。既然 TIME_WAIT 状态的持续时间是 MSL 的 2 倍,这就足以让某个方向上的分组最多存活 MSL 秒即被丢弃,另一个方向上的应答最多存活 MSL 秒也被丢弃。通过实施这个规则,我们就能保证每成功建立一个 TCP 连接时,来自该连接先前化身的重复分组都已在网络中消逝。

1.3 半连接状态: FIN_WAIT_2

若服务器发送了一个 FIN 分节给客户端,并接收到客户端回复的 ACK,但是客户端没有发送 FIN 该服务器,此时导致服务器停留在半连接状态(FIN_WAIT_2),客户端也将处于 CLOSE_WAIT 状态。

1.3.1 close 和 shutdown 的区别

  1. close 把描述符的引用计数减 1,仅在该计数变为 0 时才关闭套接字;
  2. close 终止了数据传输的两个方向;
  3. shutdown 可以有选择的终止某个方向的数据传送或者终止数据传送的两个方向;
  4. shutdown how = 1 就可以保证对方接收到一个 EOF 字符,而不管其他进程是否打开了套接字。而 close 不能保证,直到套接字引用计数值减为 0 时才会发送 EOF。也就是说直到所有的进程都关闭套接字。

1.3.2 shutdown 函数

int shutdown(int sockfd, int how);

how 的有如下取值:

  • SHUT_RD:关闭连接的读这一半。套接字中不再有数据可接收,而且套接字接收缓冲区的现有数据都被丢弃。进程不能再对这样的套接字调用任何的读函数。
  • SHUT_WR:关闭连接的写这一半。对于 TCP 套接字,这称为半关闭。但以前留在套接字发送缓冲区中的数据将被发送掉,后跟 TCP 的正常终止序列。
  • SHUT_RDWR:连接的读半部和写半部都关闭。这与调用 shutdown 两次等效:第一次调用指定 SHUT_RD,第二次调用指定 SHUT_WR。

TCP之11种状态变迁的更多相关文章

  1. (转)TCP连接的11种状态变迁

    自:http://blog.csdn.net/engrossment/article/details/8104482 http://blog.csdn.net/xiaofei0859/article/ ...

  2. TCP的11种状态

    TCP的11种状态 TCP三次握手建立连接 Tcp头部 六个标志位中,我们要用到三个: SYN:SYN= 1 表示这是一个连接请求或连接接受报文.在建立连接时用来进行同步序号(个人理解是,在建立连接的 ...

  3. [svc]tcp三次握手四次挥手&tcp的11种状态(半连接)&tcp的time-wait

    TCP的状态转化过程(11种状态)以及TIME_WAIT状态 高性能网络 | 你所不知道的TIME_WAIT和CLOSE_WAIT 我相信很多都遇到过这个问题.一旦有用户在喊:网络变慢了.第一件事情就 ...

  4. TCP的11种状态(转载)

    TCP的11种状态 TCP三次握手建立连接 Tcp头部 六个标志位中,我们要用到三个: SYN:SYN= 1 表示这是一个连接请求或连接接受报文.在建立连接时用来进行同步序号(个人理解是,在建立连接的 ...

  5. TCP协议的11种状态及其变化过程?传输的内容又是什么?

    在TCP的11种状态变迁中,我们需要用到TCP头部的三个标志位: 1.SYN,SYN=1表示这是一个连接请求报文或者连接接受报文 2.ACK,ACK=1,表示确认号生效 3.FIN,FIN=1表示发送 ...

  6. [linux] C语言Linux系统编程-TCP通信的11种状态

    三次握手由client主动发出SYN请求, 此时client处于SYN_SENT状态(第一次握手)当server收到之后会由LISTEN转变为SYN_REVD状态, 并回复client, client ...

  7. 7.2 TCP IP的11种状态

    先看TCP IP的10种状态,如下所示: 三次握手: 客户端A端发送SYN,然后进入SYN_SENT状态,服务器B端接收到SYN后,返回一个响应ACK,同时也发送一个SYN,然后B端进入SYN_RCV ...

  8. TCP三次握手和四次挥手以及11种状态

    1.三次握手 置位概念:根据TCP的包头字段,存在3个重要的标识ACK.SYN.FIN ACK:表示验证字段 SYN:位数置1,表示建立TCP连接 FIN:位数置1,表示断开TCP连接 三次握手过程说 ...

  9. python TCP协议详解 三次握手四次挥手和11种状态

    11种状态解析 LISTEN  --------------------  等待从任何远端TCP 和端口的连接请求. SYN_SENT  ---------------  发送完一个连接请求后等待一个 ...

随机推荐

  1. 百度URL链接中文转码

    百度搜索链接规则为: http://www.baidu.com/s?wd=[搜索词目]&cl=3 有多个搜索词通过加号进行链接: http://www.baidu.com/s?wd=keywo ...

  2. WebStorm 启动时提示Failed to load JVM DLL

    环境:win7 64位:时间:2019-11-18 问题描述 启动webstorm 时提示failed to load JVM DLL 解决方法 启动时快捷方式要选到64位的exe

  3. 数组去重-----js 判断字符串中是否包含某个字符串indexOf

    判断obj对象是否在arr数组里面,是返回true const dealArray = (arr, obj) => { Array.prototype.S = String.fromCharCo ...

  4. CSS基础:text-overflow:ellipsis溢出文本显示省略号的详细方法_CSS教程

    4要素: width: 125px;  //宽度必须 text-overflow: ellipsis/clip; //省略号或裁剪: white-space: nowrap;//强制内容在一行显示; ...

  5. Oracle 11.2.0.1 ADG环境MRP进程遭遇ORA

    环境:Linux + Oracle 11.2.0.1 ADG现象:发现备库没有应用日志 1. 数据库查询备库目前状态发现备库目前没有应用日志,apply lag已经显示备库有3天21小时多没有应用日志 ...

  6. mint-ui下拉加载(项目实例)

    <template> <div class="share"> <div class="header"> <div cl ...

  7. 5、vim编辑器

    1.什么是VIM? 理解为windows下面的文本编辑器,比如记事本,比如word文档 2.为什么要学? 因为在后面我们配置的服务,都需要人为修改配置,以便让程序按照我们修改后的指示运行. 1.修改配 ...

  8. OWASP Hakcing Lab在线漏洞环境

    OWASP Hakcing Lab在线漏洞环境   OWASP hakcing-lab 是一个提供免费的远程安全(Web)挑战和 OWASP TOP 10,OWASP WebGoat,OWASP Ha ...

  9. PAT Basic 1094 谷歌的招聘 (20 分)

    20 5 23654987725541023819 输出样例 1: 49877 输入样例 2: 10 3 2468024680 输出样例 2: 404 #include <iostream> ...

  10. 利用jQuery实现图片无限循环轮播(不借助于轮播插件)

    原来我主要是用Bootstrap框架或者swiper插件实现轮播图的功能,而这次是用jQuery来实现图片无限循环轮播! 用到的技术有:html.css.JavaScript(少).jQuery(主要 ...