Posts TCP 建立与释放连接
Post
Cancel

TCP 建立与释放连接

TCP 连接的建立(三次握手)

TCP 建立连接的过程叫握手,握手需要在客户端与服务器之间交换三个 TCP 报文段(简称三次握手)。

TCP 三次握手

一开始,B 的服务器进程处于 LISTEN 状态,等待客户端的连接请求。

A 的客户端进程建立 TCP 连接,向 B 发出连接请求报文段,首部中的同部位 SYN = 1,同时选择一个初始的随机序号 seq = x。这时,客户进程进入 SYN-SENT(同步已发送) 状态。

B 收到连接请求报文段后,向 A 发送确认,在确认报文段中把 SYN 和 ACK 位都设为 1,确认号 ack = x + 1,同时为自己选择一个初始序号 seq = y。这时服务器进程进入 SYN-RCVD(同步收到)状态。

A 收到 B 的确认后,还要向 B 给出确认。确认报文段的 ACK = 1,确认号 ack = y + 1,自己的序号 seq = x + 1。这时,TCP 连接已经建立,A 进入 ESTABLISHED(已建立连接)状态。

当 B 收到 A 的确认后,也进入 ESTABLISHED 状态。

TCP 规定,SYN 报文段不能携带数据,但要消耗掉一个序号,ACK 报文段可以携带数据,但如果不携带数据则不消耗序号。

为什么需要三次握手?

这主要是为了防止已失效的连接请求报文段突然又传到了 B,因而产生错误。

第一种正常情况:A 发出连接请求,但是因该请求丢失而未收到确认。于是 A 再重传一次连接请求。后来收到了确认,建立了连接。数据传输完成后,释放连接。A 发送了两个连接请求,其中第一个丢失,第二个到达 B,没有“已失效的连接请求报文段”。

第二种异常情况:A 发出的第一个连接请求没有丢失,而是在某些网络节点长时间滞留,以致延误到第二次建立的连接释放以后的某个时间才到达 B。本来是一个早已失效的报文段,但 B 收到后误以为是 A 又发出一次新的连接请求,于是向 A 发出确认报文段,同意建立连接。假定不采取三次握手,那么只要 B 发出确认,新的连接就建立了

由于现在 A 并没有发出建立连接的请求,因此不会理睬 B 的确认,也不会向 B 发送数据,但 B 缺一直等待 A 发来数据。

采用三次握手的方式,在第二种异常的情况下,A 不会向 B 发出确认,B 收不到确认,就知道 A 并有要求建立连接。

TCP 的连接释放(四次挥手)

数据传输结束后,通信的双方都可以释放连接。现在以客户端进程主动释放为例。

TCP 四次挥手

现在 A 和 B 都处于 ESTABLISHED 状态,A 的进程先发送连接释放报文段,并停止再发送数据,主动关闭 TCP 连接。A 把连接释放报文段首部的终止位 FIN 置 1,其序号 seq = u(u = 前面已经传送过的数据的最后一个字节的序号 + 1)。这时 A 进入 FIN-WAIT-1(终止等待 1)状态,等待 B 确认。

TCP 规定,FIN 报文段即使不携带数据,也要消耗一个序号。

B 收到连接释放报文段后发出确认,确认号 ack = u + 1,这个报文段自己的序号 seq = v(v = B 前面已传送过的数据的最后一个字节的序号 + 1)。然后 B 进入 CLOSE-WAIT(关闭等待)状态。这时 A 到 B 这个方向的连接就释放了,TCP 连接处于半关闭(half-close)状态,从 B 到 A 这个方向的连接还未关闭,B 发送数据,A 仍要接收。

A 收到来自 B 的确认后,进入 FIN-WAIT-2(终止等待 2)状态,等待 B 发出的连接释放报文段。

如果 B 已经没有要向 A 发送的数据,这时 B 发出连接释放报文段,使 FIN = 1。假定 B 的序号 seq = w(在半关闭状态下 B 可能又发送了一些数据)。B 还必须重复上次已经发送过的确认号 ack = u + 1。这时 B 进入 LAST-ACK(最后确认)状态,等待 A 确认。

A 在收到 B 的连接释放报文段后,必须发出确认。确认报文段中 ACK = 1,确认号 ack = w + 1,自己的 seq = u + 1(前面发送过的 FIN 报文段要消耗一个序号)。然后进入 TIME-WAIT(时间等待)状态。

现在的 TCP 连接还没有释放掉,必须经过时间等待计时器设置的时间 2MSL 后,A 才进入到 CLOSED 状态。

MSL 叫做最长报文段寿命,RFC 793 建议设为 2 分钟。TCP 允许不同的实现根据具体的情况使用更小的 MSL 值。

TIME-WAIT 状态为什么要等待 2MSL 时间?

  1. 为了保证 A 发送的最后一个 ACK 报文段能够到达 B。这个 ACK 报文段有可能丢失,因而使处在 LAST-ACK 状态的 B 收不到对已发送的 FIN + ACK 报文段的确认。B 会超时重传这个 FIN + ACK 报文段,而 A 就能在 2MSL 时间内收到这个重传的 FIN + ACK 报文段。接着 A 重传一次确认,重新启动 2MSL 计时器。最后,A 和 B 都正常进入到 CLOSED 状态。如果 A 在 TIME-WAIT 状态下不等待一段时间,那么就无法收到 B 重传的 FIN + ACK 报文段,这样 B 就无法正常进入 CLOSED 状态。

  2. 防止“已失效的连接请求报文段”出现在本连接中。A 在发送完最后一个 ACK 报文段后,再经过 2MSL,就可以使本连接持续时间内所产生的所有报文段都从网络中消失。这样就可以使下一个新的连接中不会出现这种旧的连接请求报文段。B 只要收到了 A 发出的确认,就进入 CLOSED 状态。B 结束连接的时间要比 A 早一些。

保活计时器

服务器每收到一次客户端的数据,就重新设置保活计时器,时间的设置通常是 2 小时。若 2 小时没有收到客户端的数据,服务器就发送一个探测报文段,以后每隔 75 秒发送一次。若一连发送 10 个探测报文段后仍然没有响应,服务器就认为客户端出了故障,关闭这个连接。

OLDER POST NEWER POST

Comments powered by Disqus.

内容

Search Results