传输层TCP协议——TCP连接的建立和终止

TCP连接建立:
在TCP/IP协议中,TCP协议提供可靠的连接服务,采用三次握手建立一个连接:
(1) 服务器必须准备好接受外来的连接。这通过调用socket、 bind和listen函数来完成,称为被动打开(passive open)。
(2) 第一次握手:客户通过调用connect进行主动打开(active open)。这引起客户TCP发送一个SYN(表示同步)分节(SYN=J),它告诉服务器客户将在(待建立)连接中发送的数据的初始序列号。并进入SYN_SEND状态,等待服务器的确认。 
(3) 第二次握手:服务器必须确认客户的SYN,同时自己也得发送一个SYN分节,它含有服务器将在同一连接中发送的数据的初始序列号。服务器以单个字节向客户发送SYN和对客户SYN的ACK(表示确认),此时服务器进入SYN_RECV状态。
(4) 第三次握手:客户收到服务器的SYN+ACK。向服务器发送确认分节,此分节发送完毕,客户服务器进入ESTABLISHED(已建立的)状态,完成三次握手。

传输层TCP协议——TCP连接的建立和终止_第1张图片

客户端的初始序列号为J,而服务器的初始序列号为K。在ACK里的确认号为发送这个ACK的一端所期待的下一个序列号。因为SYN只占一个字节的序列号空间,所以每个SYN的ACK中的确认号都是相应的初始序列号加1。类似地,每一个FIN(表示结束)的ACK中的确认号为FIN的序列号加1。

完成三次握手,客户端与服务器开始传送数据,在上述过程中还有一些重要概念。
未连接队列:在三次握手协议中,服务器维护一个未连接队列,该队列为每个客户端的SYN包(syn=j)开设一个条目,该条目表明服务器已收到SYN包,并向客户发出确认,正在等待客户端确认包。这些条目所标识的连接在服务器处于SYN_RECV状态,当服务器收到客户端确认包时,删除该条目,服务器进入ESTABLISHED状态。


TCP连接终止:
TCP连接终止需四个分节:
(1) 第一次挥手:某个应用进程首先调用close,我们称这一端执行主动关闭(active close)。这一端的TCP于是发送一个FIN分节,表示数据发送完毕。
(2) 第二次挥手:接收到FIN的另一端执行被动关闭(passive close)。这个FIN由TCP确认。它的接收也作为文件结束符传递给接收端应用进程(放在已排队等候应用进程接收到任何其他数据之后)。FIN的接受意味着接收端应用进程在相应连接上再无额外数据可接收。
(3) 第三次挥手:一段时间后,接收到文件结束符的应用进程将调用close关闭它的套接字。这导致它的TCP也发送一个FIN。
(4) 第四次挥手:接收到这个FIN的原发送端TCP对它进行确认。

传输层TCP协议——TCP连接的建立和终止_第2张图片

面向字节的数据传送流(如TCP字节流、Unix管道等)也使用EOF表示在某个方向上不再有数据待传送。在TCP字节流中,EOF的读或写通过收发一个特殊的FIN分节来实现。


TCP连接的分组交换:
一个完整的TCP连接所发生的实际分组交换情况,包括连接建立、数据传送和连接终止3个阶段。

客户通告一个值为536的MSS(表明该客户只实现了最小重组缓冲区大小,576(IPv4的最小重组缓冲区字节数)- 20(IPv4首部)- 20(TCP首部)),服务器通告一个值为1460的MSS(1500(以太网MTU) - 20(IPv4首部)- 20(TCP首部)),图中展示了每个端点所历经的TCP状态:

传输层TCP协议——TCP连接的建立和终止_第3张图片

一旦建立一个连接,客户就构造一个请求并发送给服务器。假设该请求适合于单个TCP分节(即请求大小小于服务器通告的值为1460字节的MSS)。服务器处理该请求并发送一个应答,假设该应答也适合于单个分节(即小于536字节)。粗箭头表示这两个数据分节。
服务器对客户请求的确认是伴随其应答发送的。这种做法称为捎带(piggybacking),它通常在服务器处理请求并产生应答的时间少于200 ms时发生。

TCP状态转换图:

TCP涉及连接建立和连接终止的操作可以用状态转换图(state transition diagram)来说明:

传输层TCP协议——TCP连接的建立和终止_第4张图片

  • TCP为一个连接定义了11种状态,并且TCP规则规定如何基于当前状态及在该状态下所接收的分节从一个状态转换到另一个状态。
当某个应用进程在CLOSED状态下执行主动打开时,TCP将发送一个SYN,且新的状态是SYN_SENT。如果这个TCP接着接收到一个带ACK的SYN,它将发送一个ACK,且新的状态是ESTABLISHED。这个最终状态是绝大多数数据传送发生的状态。
  • 自ESTABLISHED状态引出的两个箭头处理连接的终止。
如果某个应用进程在接收到一个FIN之前调用close(主动关闭),那就转换到FIN_WAIT_1状态。
如果某个应用进程在ESTABLISHED状态期间接收到一个FIN(被动关闭),那就转换到CLOSE_WAIT状态。
  • 同时打开(simultaneous open),发生在两端几乎同时发送SYN并且这两个SYN在网络中交错的情形下。同时关闭(simultaneous close),发生在两端几乎同时发送FIN的情形下。
TIME_WAIT状态:
执行主动关闭的一端经历了 TIME_WAIT状态。该端点停留在这个状态的持续时间是最长分节生命期(maximum segment lifetime,MSL)的两倍,有时候称之为2MSL。

       任何TCP实现都必须为MSL选择一个值。RFC 1122的建议值是2分钟,不过源自Berkeley的实现传统上改用30秒这个值。这意味着TIME_WAIT状态的持续时间在1分钟到4分钟之间。 MSL是任何IP数据报能够在因特网中存活的最长时间。我们知道这个时间是有限的,因为每个数据报含有一个称为跳限(hop limit)的8位字段(IPv4的TTL字段和IPv6的跳限字段),它的最大值为255。尽管这是一个跳数限制而不是真正的时间限制,我们仍然假设: 具有最大跳限(255)的分组在网络中存在的时间不可能超过MSL秒。
       分组在网络中"迷途"通常是路由异常的结果。某个路由器崩溃或某两个路由器之间的某个链路断开时,路由协议需花数秒钟到数分钟的时间才能稳定并找出另一条通路。在这段时间内有可能发生路由循环(路由器A把分组发送给路由器B,而B再把它们发送回A),我们关心的分组可能就此陷入这样的循环。假设迷途的分组是一个TCP分节,在它迷途期间,发送端TCP超时并重传该分组,而重传的分组却通过某条候选路径到达最终目的地。然而不久后(自迷途的分组开始其旅程起最多MSL秒以内)路由循环修复,早先迷失在这个循环中的分组最终也被送到目的地。这个原来的分组称为迷途的重复分组(lost duplicate)或漫游的重复分组(wandering duplicate)。TCP必须正确处理这些重复的分组。

TIME_WAIT状态有两个存在的理由:
  • 可靠地实现TCP全双工连接的终止
  • 允许老的重复分节在网络中消逝


你可能感兴趣的:(网络编程,tcp)