zoukankan      html  css  js  c++  java
  • [TCP IP详解:学习笔记]TCP连接的建立与终止

           TCP是一个面向连接的协议,无论哪一方向另一方发送数据之前,都必须先在双方之间家里一条连接。为了建立一条TCP连接(如图1所示):

    1. 请求段(客户端)发送一条SYN段指明客户打算连接服务器的端口,以及初始序号(即ISN)。这个SYN端为报文段1;
    2. 服务器端发回包含服务器的初始序号的SYN报文段作为应答。同时,将确认序号设置为客户的ISN加1以对客户的SYN报文段的确认。一个SYN将占用一个序号;
    3. 客户必须将确认序号设置为服务器的ISN加1以对服务器的SYN报文段进行确认。

      发送第一个SYN的一端将执行主动打开(action open),接收这个SYN并发回下一个SYN的一端执行被动打开(passive open)。

      当一端为建立连接而发送它的SYN时,它为连接选择了一个初始序号。ISN随着时间而变化,因此每个连接都有不同的ISN。这样可以有效的防止在网络中被延迟的分组在以后又被传送过来,而导致某个连接的一方对它做出错误的解释。

     

    图1 连接建立期间报文段的正常交换

     

           连接终止协议

           建立一个TCP连接需要三次握手,而终止一个连接需要经过四次握手。这是由于TCP的半关闭(half-close)造成的。既然一个TCP连接时全双工(即数据在两个方向上能同时传递),因此每个方面必须单独地进行关闭。

           需要注意的是,收到一个FIN只意味着在这一方向上没有数据流动,但一个TCP连接在收到一个FIN之后仍能发送数据。

           TCP连接终止过程,如图2所示

    1. TCP客户端发送一个FIN,用来关闭从客户端到服务器的数据传送;
    2. 当服务器收到这个FIN,它发回一个ACK,确认序号为收到的序号加1。一个FIN也将占用一个序号;
    3. 服务器程序首先传送一个文件结束符,然后服务器关闭它的连接,发送一个FIN到客户端;
    4. 客户端回复一个确认。

      最大报文段长度(MSS)表示TCP传往另一端的最大块数据块的长度。当建立一个TCP连接时,每一方都有用于通告它期望接收的MSS选项(MSS选项只能出现在SYN报文段中)。如果一方没有接收到来自另一方的MSS值,则MSS就定为默认值536字节(这个默认值允许20字节的IP首部和20字节的TCP首部以适合576字节的IP数据报)。MSS让主机限制另一端发送数据报的长度,加上主机也能控制它发送数据报的长度,这将使以较小MTU接收到一个网络上的主机避免分段。

     

    图2 TCP连接终止期间报文段的正常交换

           半连接:TCP连接的一端在结束它的发送之后还能接收到来自另一端数据的能力。

           TCP的状态变迁图(如图3所示):

           ESTABLISHED状态是连接双方能够进行双向数据传送的状态。

           当SYN_RCVD(图中SYN收到)状态是从LISTEN状态(正常情况)进入,而不是从SYN_SENT状态(同时打开)进入时,从SYN_RCVD回到LISTEN状态变迁才是有效的。这意味着如果执行被动打开(进入LISTEN),收到一个SYN,发送一个带ACK的SYN(进入SYN_RCVD),然后收到一个RST,而不是一个ACK,便又回到LISTEN状态并等待另一个连接请求的到来。

           TIME_WAIT状态也成为2MSL等待状态。当TCP执行一个主动关闭,并发回最后一个ACK,该连接必须在TIME_WAIT状态停留的时间为2倍的MSL。这样可让TCP再次发送最后的ACK以防这个ACK丢失(另一端超时并重发组后的FIN)。

           一个socket对(即包含本地IP地址、本地端口、远端IP地址和远端端口的4元组)在TCP连接处于2 MSL等待期间,将不能再次被使用。尽管许多具体的实现中允许一个进程重新使用仍处于2 MSL等待的端口(通常是设置选项SO_REUSEADDR),但TCP不能允许一个新的连接建立在相同的插口上。

           无论何时一个报文段发往基准的连接(即,由目的IP地址和目的端口号 以及源IP地址和源端口号指明的连接)出现错误,TCP都会发回一个复位报文段。

           异常终止(发送一个复位(RST)报文段而不是FIN来中途释放一个连接)一个连接对应用程序来说有两点好处:

    1. 丢弃任何待发数据并立即发送复位报文段;
    2. RST的接收方会区分另一端执行的是异常关闭还是正常关闭。

      在正常关闭的情况,需要在所有排队数据都已发送之后才发送FIN。因此,正常情况下没有任何数据丢失。

      Socket API通过“linger to close”选项(SO_LINGER)提供这种异常关闭的能力。

     

     

    图3 TCP的状态变迁图

          

           如果一方已经关闭或异常终止连接而另一方却还不知道,这样的TCP连接成为半打开(Half-Open)的。任何一端的主机异常都可能导致这种情况的发生。只要不打算在半打开连接上传输数据,仍处于连接状态的一方就不会检测另一方已经出现异常。

           发生半打开连接的另一个常见原因是,当客户主机突然掉电而不是正常的结束客户应用程序后在关机。

           TCP连接在同时打开的情况下,仅建立 一条连接而不是两条连接。图4显示了同时打开期间报文段的交换。两端几乎在同时发送SYN,并进入SYN_SENT状态。当每一端收到SYN时,状态为SYN_RCVD,同时它们都再发送SYN并对收到的SYN进行确认。当双方都收到SYN及相应的ACK时,状态都边前卫ESTABLISHED。因此,一个同时打开的连接需要交换4个报文段

          

    图4 同时打开期间报文段的交换

           同时关闭:当应用层发送关闭命令时,两端均从ESTABLISHED变为FIN_WAIT_1。这将导致双方各发送一个FIN,两个FIN经过网络传送后分别到达另一端。收到FIN后,状态由FIN_WAIT_1变迁到CLOSING,并发送最后的ACK。当收到最后的ACK时,状态变化为TIME_WAIT。图5总结了这些变化。

     

    图5 同时关闭期间的报文段交换

           图6显示了当前TCP选项的格式,这些选项的定义来自于RFC 793和RFC 1323。每个选项的开始是1字节kind字段,说明选项的类型。

     

    图6 TCP选项

  • 相关阅读:
    cf C. Vasya and Robot
    zoj 3805 Machine
    cf B. Vasya and Public Transport
    cf D. Queue
    cf C. Find Maximum
    cf B. Two Heaps
    cf C. Jeff and Rounding
    cf B. Jeff and Periods
    cf A. Jeff and Digits
    I Think I Need a Houseboat
  • 原文地址:https://www.cnblogs.com/life91/p/3001959.html
Copyright © 2011-2022 走看看