Zach的博客

TCP连接建立和终止

TCP连接的建立和终止

TCP连接建立

建立一个TCP连接的过程图示如下(图片均来源于网络…):

shakehand3.jpg
  1. 服务器在连接建立之前必须准备好接收客户发来的连接,这一般通过创建套接字,绑定服务器地址、监听套接字来完成,即socketbindlisten三个函数。这一个过程被成为被动打开。
  2. 客户通过connect函数发起主动打开,客户会发送一个SYN分节,它告诉服务器客户将在连接中发送的数据的初始序列号,通常该分节不带数据,其所在IP数据只含有一个IP首部、一个TCP首部以及可能的TCP选项。
  3. 服务器收到客户发来的SYN分节后,服务器必须确认该分节,同时服务器发送一个自己的SYN分节,它含有服务器将在该连接中发送的数据的初始序列号。
  4. 客户收到服务器发回的消息后,确认服务器的分节,连接建立。

从图中可以看到ACK是SYN分节的序列号加1,类似的,FIN分节的ACK也是FIN分节的序列号加1。

TCP连接终止

TCP终止一个连接需要4个分节。

终止一个连接的图示如下:

shakehand4.jpg
  1. 某个应用首先调用close,该端主动关闭,发送一个FIN分节
  2. 接收到FIN分节的对端执行被动关闭,这个FIN由TCP确认,FIN分节的接收也作为一个文件结束符(EOF)传递给接收端应用进程。
  3. 一段时间之后,接收到这个文件结束符的引用进程将调用close关闭它的套接字,这会导致它也发送一个FIN分节。
  4. 接收这个最终FIN的对端发送一个ACK确认这个FIN分节。

连接和终止

一个完整的连接和终止的过程示意:

full_process.jpg

一个完整的TCP状态转换图:

state.jpg

TIME_WAIT

TCP终止中,执行了主动关闭的那端在接收到对端发来的FIN分节和发送对应的ACK之后就进入了TIME_WAIT状态,该状态的持续时间是2个MSL(maximum segment lifetime)。它的存在有两个理由:

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

对于第一个理由,如果最后的ACK丢失了,那么服务器需要重发FIN,因此客户必须维护状态信息,以允许它发送最终的那个ACK,如果客户不维护状态信息,那么客户在收到服务器重传的FIN后将直接相应RST,这个分节将会被服务器解释为一个错误。

对于第二个理由,假设在一个连接被终止了马上又发起来一个相同IP和端口上的连接,后一个连接成为前一个连接的化身,TCP必须防止老的连接的分组在老连接结束之后再现,以防止其被误解为新的连接的分组。TCP不会让处于TIME_WAIT状态的连接发起新的化身,既然TIME_WAIT的时间是MSL的2倍,这就足以让某个方向上的分组最多存活MSL时间即被丢弃,另外一个方向上的应答最多存活MSL时间也被丢弃。通过这种方式,老的重复分组在网络中都已经消逝。