美文网首页
TCP(一) 建立连接 & 连接释放

TCP(一) 建立连接 & 连接释放

作者: 又语 | 来源:发表于2021-11-10 19:48 被阅读0次

    TCP是一个面向连接的服务,建立连接需要经过三次握手,释放连接需要经过四次挥手。

    三次握手

    客户端与服务器交互需要 3 个数据包,握手的主要作用就是为了确认双方的接收和发送能力是否正常,初始序列号、交换窗口大小以及 MSS 等信息。

    • 第一次握手
      客户端发送请求连接数据包到服务器,标志位SYN置为1,初始序号seq随机生成,即SYN=1 seq=x,客户端进入SYN_SENT状态,等待服务器回复。

    • 第二次握手
      服务器收到连接请求数据包后根据标志位SYN=1知道客户端在请求建立连接,服务器将标志位SYNACK都置为1ack=x+1,随机生成一个初始序号seq=y,并将该数据包(SYN=1 ACK=1 seq=y ack=x+1)回复给客户端确认连接请求,服务器进入SYN_RCVD状态。

    • 第三次握手
      客户端收到确认后检查ack是否为x+1ACK是否为1,如果正确则将标志位ACK置为1ack=y+1,并将该数据包(ACK=1 seq=x+1 ack=y+1)发送给服务器,发送完成后客户端进入ESTABLISHED状态,服务器接收到后检查ack是否为y+1,如果正确则连接建立成功,服务器进入ESTABLISHED状态。随后客户端与服务器间可以开始传输数据。

    四次挥手

    • 第一次挥手
      客户端发起FIN包(FIN=1 seq=u),客户端进入FIN_WAIT_1状态。TCP 规定,即使FIN包不携带数据,也要消耗一个序号。

    • 第二次挥手
      服务器收到FIN包,发出ACK确认包,并带上自己的序号seq=vACK=1 seq=v ack=u+1),服务器进入CLOSE_WAIT状态。此时客户端已经没有数据需要发送给服务器了,但服务器如果仍有数据发送给客户端的话,客户端依然需要接收。客户端接收到服务器发送的ACK后进入FIN_WAIT_2状态。

    • 第三次挥手
      服务器数据发送完成后向客户端发送FIN包(FIN=1 seq=w ack=u+1),半连接状态下服务器可能又发送了一些数据,假设发送seqw,服务器进入LAST_ACK状态。

    • 第四次挥手
      客户端接收到服务器的FIN包后发出确认包ACK=1 seq=u+1 ack=w+1,客户端进入TIME_WAIT状态,此时TCP连接还没有释放,必须经过2*MSL后才进入CLOSED状态,而服务器接收到客户端的ACK后就进入了CLOSED状态,服务器结束TCP连接的时间要比客户端早一些。

    思考

    1 为什么建立连接需要握手三次,两次行不行?
    • 原因一:TCP连接建立前需要确认客户端和服务器双方的收发包能力:
      • 第一次握手可以让服务器知道客户端的发送能力是正常的
      • 第二次握手可以让客户端知道服务器的接收和发送能力都是正常的
      • 第三次握手可以让服务器指导客户端的接收能力是正常的
        所以只有经历三次握手才能让客户端和服务器双方都确认对方的收发能力是否正常。
    • 原因二:确保序列号可靠同步
      第二次握手服务器向客户端发送了自己的初始序列号,如果第二次握手报文丢失则客户端就无法知道服务器的初始序列号,所以需要第三次握手让服务器知道客户端已确认服务器的初始序列号。
    • 原因三:阻止重复历史连接的初始化
      客户端由于某种原因发送了两个不同序号的SYN包,因为复杂的网络环境中旧的数据包有可能先到达服务器,如果是两次握手则服务器收到旧的SYN包就会立刻建立连接,从而造成网络异常。如果是三次握手,服务器需要回复SYN+ACK包,客户端会对比应答的序号,如果发现是旧的报文就会给服务器发RST包,直至正确的SYN包到达服务器后才正常建立连接。
    • 原因四:安全问题
      TPC新建连接时内核会为连接分配一系列内存资源,如果采用两次握手可能会放大DDOS攻击。
    2 三次握手可以携带数据吗?

    第一次握手和第二次握手不可以携带数据,第三次握手可以携带数据。假如第一次握手携带数据,如果碰到恶意攻击,那么每次在第一次握手的SYN报文中都会加入大量数据,会造成服务器花费大量存储空间来缓存这些数据。

    3 为什么释放连接是四次,比建立连接多一次?

    建立连接时服务器的SYNACK是合并发送的,而因TCP是全双工通信,释放连接过程中在客户端发送FIN包后,服务器可能还有数据需要发送,不能立即关闭连接,所以不能同时发送FIN包和ACK包,只能先确认ACK,然后等服务器无数据发送时再发送FIN包。

    4 为什么TIME_WAIT状态需要经过2MSL才能返回到CLOSED状态?

    MSL是指报文在网络中的最大生存时间。

    • 原因一:在客户端回复服务器FIN包的确认包ACK后,这个ACK包可能是不可达的,如果服务器收不到ACK的话需要重新发送FIN包。所以客户端发送ACK后需要留出2MSL时间(ACK到达服务器的时间 + 服务器重发FIN包时间),如果客户端等到2MSL后没有收到服务器重传的FIN包,说明可以确认服务器已经收到了客户端发送的ACK包。
    • 原因二:客户端发送完最后一个ACK包后,再经过2MSL时间就可以使当前连接持续的时间内所产生的所有报文都从网络中小时,使下一个新的连接中不会出现这种旧的连接请求报文。

    相关文章

      网友评论

          本文标题:TCP(一) 建立连接 & 连接释放

          本文链接:https://www.haomeiwen.com/subject/cvxpzltx.html