zoukankan      html  css  js  c++  java
  • TCP的三次握手和四次握手

    三次握手(建立连接)

    1. 首先,服务器进程(B)先创建传控制块TCB(用来存储连接信息,如连接表,发送和接收序号等),准备接收客户进程(A)的请求。然后服务器进程处于LISTEN(收听)状态,等待客户的连接请求。客户进程(A)同样也是首先创建传输控制块TCB,然后向服务器B发出连接请求报文。报文首部的同步位SYN=1,同时选择一个初始的序号seq=x(TCP规定,SYN=1的报文不能携带数据,但是要消耗掉一个序号),这时TCP客户进程进入SYN-SENT(同步已发送)状态。
    2. 服务器进程(B)收到连接请求后,如同意连接,则向A发送确认。在确认报文中SYN位和ACK位都为1,确认号ack=x+1,同时自己选择一个初始序号seq=y。(这个报文也不能携带数据,同样要消耗一个序号),这是服务器进程(B)进入SYN-RCVD(同步收到)状态。
    3. 客户进程(A)收到B的确认后,还要向B发送确认。确认报文的ACK=1,确认号为ack=y+1,自己的序号为seq=x+1,(TCP规定,ACK报文可以携带数据,如果不携带则不消耗序号,这样的话,下一个数据报文段的序号仍是seq=x+1),这时,TCP连接已建立,A进入ESTABLISHED状态,当B收到A的确认后,同样也进入ESTABLISHED状态。

    问题:为什么A还要发送一次确认呢?(为什么是三次握手,不是两次)

    答:主要是为了防止已经失效的连接请求报文突然又传送到B,因而产生错误。例如,当A发送连接请求,但是因为网络延迟等原因,在某个网络节点滞留,迟迟未到达B,所以A未收到B的确认,这时候A重新发送了一次请求报文,这次正常建立连接。数据传输完毕后,正常释放连接。突然这时候B收到了A第一次发送的请求报文,以为A又要重新建立连接。这时发送了确认报文,同意建立连接。如果这时不采用三次握手,那么只要B发送确认,新的连接就建立了。由于A没有发出建立连接的请求,因此不会搭理B,也不会向B发送数据,而B以为新的连接建立了,一直在等待A发来数据,B的许多资源就这样白白浪费了。这种情况下,如果采用三次握手,A不会向B发送确认,B由于收不到确认,就知道A没有建立连接。

    四次握手(释放连接)

    1. 双方传输结束后,通信双方都可以释放连接。现在A和B都处于ESTABLISHED状态。A进程向B发送连接释放报文,并停止发送数据。报文的首部终止控制位FIN=1,序号为u(序号u等于前面传送过的数据的最后一个字节的序号加1),这是A进入FIN-WAIT-1(终止等待1)状态,等待B的确认。
    2. B收到连接释放报文后即发出确认ACK=1,确认号为ack=u+1,而这个报文的自己序号是v(等于B前面已传送过的数据的最后一个字节的序号加1)。然后B进入CLOSED-WAIT(关闭等待)状态。(TCP服务器进程这时应通知高层应用进程,因而A到B的连接就释放了,这时候TCP连接进入半关闭状态,即A已经没有数据要发送了,但是如果B要发送数据,A仍要接收,也就是说从B到A这个方向的连接并未关闭)。A收到来自B的确认后,就进入FIN-WAIT-2(终止等待2)状态,等待B发出的连接释放报文段。
    3. 如果B没有数据向A发送了,其应用进程就通知TCP释放连接。这是B发送连接释放报文必须使FIN=1,假定B的序号为w,(因为在半关闭状态B可能又发送了一些数据),B必须重复上次已发送的确认号ack=u+1,确认位ACK=1。这时B进入LAST-ACK(最后确认)状态,等待A的确认。
    4. A收到B的连接释放报文后,必须对此发出确认。在确认报文中把ACK置为1,确认号为ack=w+1,而自己的序号是seq=u+1,然后进入TIME-WAIT(时间等待)状态。请注意,现在TCP连接还没有释放掉,必须经过时间等待计时器(TIME-WAIT timer)设置的时间2MSL后,A才进入CLOSED状态。(MSL-Maximum Segment Lifetime叫做最长报文段寿命,建议为2分钟),因此A进入到TIME-WAIT状态后,要经过4分钟才能进入到CLOSED状态,才能开始建立下一个新的连接。

    问题:为什么A在TIME-WAIT状态必须等待2MSL的时间呢?

    答:为了保证A发送的最后一个ACK报文段能够到达B。这个ACK报文段有可能丢失,因此处于LAST-ACK状态的B收不到对已发送的FIN+ACK报文段的确认。B会超时重传这个FIN+ACK报文段,而A就能在2MSL时间内收到这个重传的FIN+ACK报文段。接着A重传一次确认,重新启动2MSL计时器。最后A和B都正常进入到CLOSED状态。如果A不等待一段时间,而是立即释放连接,那么就无法收到B的重传FIN+ACK报文段,因而也不会再发送一次确认报文段。这样,B就无法按照正常的步骤进入CLOSED状态。另一个原因是,防止已失效的连接请求报文段出现在本连接中,A在发送完最后一个ACK报文段后,再经过2MSL,就可以使本连接持续的时间内所产生的所有报文段都从网络中消失。这样就可以使得下一个新的连接中不会出现这种旧的连接请求报文段。

  • 相关阅读:
    编译安装dropbear
    ssh的相关实验
    通过ssh协议实现用户key认证登录
    cobbler实现自动安装
    Centos 6 PXE安装
    Centos 7 PXE一键安装
    openssl命令
    实现CA证书创建及客户端申请证书
    android 动画
    BottomSheetBehavior 结合CoordinatorLayout实现底部栏
  • 原文地址:https://www.cnblogs.com/neuzk/p/9476411.html
Copyright © 2011-2022 走看看