TCP连接的建立和终止

2014-05-27 22:50:37   最后更新: 2016-04-18 21:24:46   访问数量:1286




建立一个TCP连接的过程如下:

  1. 服务器必须准备好接收外来的连接,这通常通过调用 socket、bind 和 listen 三个函数完成,我们称之为“被动打开”
  2. 客户通过调用 connect 发起“主动打开”,这导致客户TCP发送一个SYN(同步)分节,它告诉服务器客户将在(待建立的)连接中发送的数据的初始序列号,通常SYN分节不携带数据,其所在IP数据报只含有一个IP首部、一个TCP首部以及可能有的TCP选项
  3. 服务器必须确认(ACK)客户的 SYN,同时自己也得发送一个 SYN 分节,他含有服务器将在同一个 连接中发送的数据的初始序列号,服务器在单个分节中发送 SYN 和对客户 SYN 的 ACK(确认)
  4. 客户必须确认服务器的 SYN

 

过程如下图所示,因为这种交换至少需要三个分组,所以称之为“三路握手”

 

图中,客户的初始序列号为 j,服务器的初始序列号为 k,ACK 中的确认号是发送这个 ACK 的一段所期待的下一个序列号,因为 SYN 占据一个字节的序列号空间,所以每个 SYN 的 ACK 中的确认号就是该 SYN 的初始序列号加1,类似的,每一个 FIN(结束)的 ACK 中的确认号为该 FIN 的序列号加1

 

举例

  1. 建立一个 TCP 连接就好比一个电话系统
  2. socket 函数等同于有电话可用
  3. bind 函数就是告诉别人你的电话号码
  4. listen 函数是打开电话的振铃功能,这样你才可以在来电话的时候听到
  5. 当你知道对方的电话号码,就可以使用 connect 函数来拨打过去
  6. accept 函数返回客户的标识,类似于电话的来电显示
  7. 如果使用域名系统 DNS,他就提供了一个电话簿的功能,使用 getaddrinfo 函数可以在电话簿中查找某人的号码,而 getnameinfo 则以电话号码为关键字进行查找对方名字的服务

 

每一个 SYN 可以含有多个 TCP 选项

  • MSS选项

发送 SYN 的 TCP 一端使用本选项通告对端他的最大分节大小,也就是他在本连接的每个 TCP 分节中愿意接受的最大数据量,使用 TCP_MAXSEG 套接字选项可以提取和设置这个 TCP 选项

  • 窗口规模选项

TCP 连接任何一段能够通告对端的最大窗口大小(他一次所能接收的数据量)是 65535,因为在 TCP 首部中相应的字段占有16 bits,然而现今因特网上已经普及的高速连接要求更大的窗口以获得更大的吞吐量,因此需要提供该选项 窗口规模选项指定 TCP 首部中的通告窗口必须扩大的位数(0~14),因此,TCP 连接最大可以提供接近 1GB 的窗口,但是前提是一个 TCP 连接上的两端必须都支持这个选项,我们可以使用 SO_RCVBUF 套接字选项影响这个 TCP 选项

  • 时间戳选项

这个选项对于告诉网络连接是必要的,他可以防止由于延迟而在已经被丢弃后却最终到达对端的分组可能造成的数据损坏

 

对于窗口规模选项和时间戳选项,是两个较新的选项,对于早期实现,并不支持这两个个选项,但是这并不要紧,因为当发送端在 SYN 中发送了该选项,虽然接收端收到后并不能理解这个选项,但是对于绝大多数实现,他们对于自己所不能理解的选项会选择忽略,这样,客户返回的 SYN 中就不会具有该选项,服务器端就会按照默认的16位窗口进行通信

 

高带宽或长延迟的网络被称为“长肥管道”,因此这两个选项也被称为“长肥管道选项”

 

TCP 建立一个连接需要三个分节,而终止一个连接则需要四个分节:

  1. 某个应用进程首先调用 close 函数发起“主动关闭”,发送一个 FIN 分节,表示数据发送完毕
  2. 另一端接受到这个 FIN 执行“被动关闭”,这个 FIN 由 TCP 确认,他的接收也作为一个文件结束符传递给接收端应用进程,意味着结合艘段应用进程在相应连接上再无额外数据可接收
  3. 一段时间后,接收到这个文件结束符的应用进程将调用 close 函数关闭他的套接字,这导致他的 TCP 也发送一个 FIN
  4. 接收这个最终 FIN 的原发送端 TCP 确认这个FIN

 

由于每个方向都需要一个 FIN 和一个 ACK,因此通常需要四个分节,但是某些情况下步骤1中的 FIN 岁数据一起发送,步骤2和步骤3也有可能被合并成一个分节,如下图所示

 

与 SYN 类似,一个 FIN 也占据一个字节的序列号空间,因此,每个 FIN 的 ACK 确认号就是这个 FIN 号加 1

 

需要指出,无论是客户端还是服务器端都可以执行主动关闭,虽然通常情况是客户端执行主动关闭,但是某些协议,如HTTP/1.0却是由服务器端发起主动关闭的

 

TCP 设计连接建立和连接诶终止的操作可以用转换图来说明:

 

TCP 为一个连接定义了11种状态,并且 TCP 规则规定了如何从一个状态转换到另一个状态

这些状态可以使用 netstat 工具显示,这个工具是一个在调试客户/服务器应用时很有用的工具

 

上图中我们看到执行主动关闭的过程中经历了 TIME_WAIT 状态,该端点停留在这个状态的持续时间是最长分节生命时期(MSL)的两倍,因此有时成为2MSL

任何 TCP 实现都必须为 MSL 选择一个值,一般为2分钟或30秒,这就意味着 TIME_WAIT 状态持续时间在1分钟到4分钟之间,MSL 是任何 IP 数据报能够在因特网中存活的最长时间

每个数据报含有一个称为“跳限”的8位字段,他的最大值是255,每当经过路由器转发时都会将原有的跳限值减1,但是即使具有最大跳限的分组在网络中存在的时间也不能超过MSL秒

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

  • 可靠的实现 TCP 全双工连接的终止
  • 允许老的重复分节在网络中消逝

如果最终 ACK 丢失,服务器将重新发送最终的 FIN,那样对端必须重新发送 ACK,如果不进入 TIME_WAIT 状态则会造成另一端无法完成关闭

另一方面,如果没有 TIME_WAIT 状态,在一个 MSL 秒内,连接关闭,并且马上使用相同的地址和相同的端口建立另一个连接,这时新的连接可能会收到旧的连接的重复分节,由于任何 IP 数据报最长只能在网络中存活 MSL 秒,那么只要等待 2MSL 秒,就不会出现这样的问题了,因为来自该连接先前化身的老的重复分组都已经在网络中消逝了

 

下图展示了一个完整的 TCP 连接所发生的实际分组交换情况及每个端点所经历的 TCP 状态,包括连接建立、数据传送和连接终止三个阶段

 

MSS 为1460是IPv4以太网中的典型值,不同方向上的 MSS 值不同不会有任何问题

在上例中,服务器处理客户端的请求并发送一个应答,二者伴随发送,这种做法被称为“稍待”,它通常在服务器处理请求并产生应答的时间少于200ms时发生,如果服务器耗时更长,那么就会先确认后应答

图中可以看出,TCP 连接的建立和终止所需要的开销是非常巨大的

 






读书笔记      技术帖      linux      unix      计算机网络      unp      tcp      网络编程      socket      三次握手      四次挥手      ack      龙潭书斋     


京ICP备15018585号