TCP创建链接的过程叫作握手,握手须要在客户和服务器之间交换三个 TCP 报文段。html
最初,客户端和服务器的 TCP 进程都处于 CLOSED (关闭) 状态。B 的 TCP 服务器进程先建立 传输控制块 TCB ,准备接受客户进程的链接请求。而后服务器进程处于 LISTEN (收听) 状态,等待客户的链接请求。A 的 TCP 客户进程也是首先建立 传输控制块 TCB 。
服务器
第一次握手 : 客户端打算创建链接时,向服务器发出链接请求报文段,此时首部中的同步位 SYN = 1 ,同时选择一个初始须要 seq = x 。 TCP 规定,SYN = 1 的报文段 不能携带数据,但要消耗掉一个序号。这时,TCP 客户进程进入 SYN-SENT (同步已发送)状态。
网络
第二次握手:服务器收到链接请求报文段后,若是赞成创建链接,则向客户端发送确认。在确认报文段中应把 SYN 位 和 ACK 位 都置 1 ,确认号是 ack = x + 1,同时也为本身选择一个初始序号 seq = y。(这个报文段也不能携带数据,但一样要消耗掉一个序号。)这时 TCP 服务器进程进入 SYN-RCVD (同步收到) 状态。
计算机网络
第三次握手:客户端收到服务器的确认后,还要向服务器给出确认。确认报文段的 ACK 置为 1 ,确认号 ack = y + 1,而本身的序号 seq = x + 1 。这时, TCP 链接已经创建,客户端进入 ESTABLISHED (已创建链接) 状态。当 服务器 收到 客户端 的确认后,也进入 ESTABLISHED (已创建链接) 状态。3d
经过这样的三次握手,客户端与服务器端创建可靠的双工的链接,开始传送数据。三次握手的主要目的是保证链接是双工的,可靠更可能是经过重传机制来保证的。
cdn
主要是为了防止已失效的链接请求报文段忽然又传到了 服务器,于是产生错误。 htm
现假定出现一种异常状况,即 客户端 发出的第一个链接请求报文段并无丢失,而是在某些网络结点长时间滞留了,以至延误到链接释放之后的某个时间才到达 服务器。原本这是一个早已失效的报文段。但 服务器 收到此失效的链接请求报文段后,就误认为是 客户端 又发出一次新的链接请求。因而就向 客户端 发出确认报文段,赞成创建链接。假定不采用报文握手,那么只要 服务器发出确认,新的链接就创建了。因为如今 客户端 并无发出创建链接的请求,所以不会理睬 服务器 的确认,也不会向 服务器 发送数据。可是 服务器 却觉得新的运输链接已经创建了,并一直等待 客户端 发来数据。服务器 的许多资源就这样白白浪费了。 采用三次报文握手的办法,能够防止上述现象的发生。假如在刚才的异常状况下,客户端 不会像 服务器 的确认发出确认。服务器 因为收不到确认,就知道 客户端 并无要求创建链接。
blog
数据传输结束后,通讯的双方均可以释放资源。此时 客户端 和 服务器 都处于 ESTABLISHED 状态。进程
第一次握手 : 客户端 的应用进程先向其 TCP 发出链接释放报文段,并中止在发送数据,主动关闭 TCP 链接。客户端把链接释放报文段首部的终止控制位 FIN 置 1,其序号 seq = u ,它等于前面已传过的数据的最后一个字节的序号加 1 。这时 客户端 进入 FIN-WAIT-1 (终止等待1) 状态,等待 服务器 的确认。( FIN 报文段即便不携带数据,它也消耗掉一个序号。)
资源
第二次握手:服务器收到链接释放报文段后即发出确认,确认号 ack = u + 1 ,而这个报文段 本身的序号是 v ,等于 服务器 前面已经传过的数据的最后一个字节的序号加 1 。而后 服务器 就进入 CLOSEWAIT(关闭等待)状态。TCP 服务器进程这时应通知高层应用进程(不肯定本身是否还有数据要发送给 客户端(因此是四次不是三次)),于是从 客户端 到 服务器 这个方向的链接就释放了,这时的 TCP 链接处于 半关闭(Half-close)状态,即 客户端 已经没有数据要发送了,但 服务器 若发送数据,客户端仍要接收。也就是说, 服务器 到 客户端 这个方向的链接并未关闭,这个状态可能会持续一段时间。
客户端 收到来自 服务器 的确认后,就进入 FIN-WAIT-2(终止等待2) 状态,等待 服务器 发出的链接释放报文段。
第三次握手:若 服务器 已经没有要向 客户端 发送的数据,其应用进程就通知 TCP 释放链接。这时 服务器发出的链接使用报文段必须使用 FIN = 1。现假设 服务器 的序号为 w(在半关闭状态 服务器 可能又发送了一些数据)。服务器还必须重复上次已发送过的确认号 ack = u + 1。这时 服务器 就进入 LAST-ACK (最后确认) 状态,等待 客户端 的确认。
第四次握手:客户端 在收到 服务器 的链接释放报文段后,必须对此发出确认。在确认报文段中把 ACK 置 1,确认号 ack = w + 1,而本身的序号是 seq = u + 1(根据 TCP 标准,前面发送过的 FIN 报文段要消耗一个序号)。而后进入到 TIME-WAIT(时间等待) 状态。请注意,TCP 链接如今尚未释放掉。必须通过 时间等待计时器(TIME-WAIT)设置的时间 2MSL 后,客户端 才进入到 CLOSED 状态。时间 MSL 叫作 最长报文段寿命,RFC 793 建议设为 2 分钟。
第一,为了保证 客户端 发送的最后一个 ACK 报文段可以到达 服务器。这个 ACK 报文段有可能丢失,于是使 服务器 收不到确认。服务器 会超时重传这个 FIN + ACK 报文段,而 客户端 就能在 2MSL 时间内收到这个重传的报文段。接着 客户端 重传一次确认,从新启动 2MSL 计时器。最后,客户端 和 服务器 都能正常进入到 CLOSED 状态。若是 客户端 在 TIME-WAIT 状态不等待一段时间,而是在发送完 ACK 报文段后当即释放链接,那么就没法收到 服务器 重传 的 FIN+ACK 报文段,于是也不会再发送一次确认报文段。这样,服务器 就没法按照正常步骤进入 CLOSED 状态。
第二,防止“已失效的链接请求报文段” 出如今本次链接中。客户端 在发送完最后一个 ACK 报文段后,再通过 2MSL,就可使本次链接持续的时间内所产生的全部报文段都从网络中消失。这样就可使下一个新的链接中不会出现这种旧的链接请求报文段。
TCP 设有一个 保活计时器。服务器每收到一次客户的数据,就从新设置保活计时器,时间的设置一般是两小时。若两小时没有收到客户的数据,服务器就发送一个 探测报文段 ,之后则每隔 75 秒钟发送一次。若一连发送 10 个探测报文段后仍无客户的响应,服务器就认为客户端出了故障,接着就关闭这个链接。
参考:《计算机网络》谢希仁