zoukankan      html  css  js  c++  java
  • java Interview 8:通讯协议

    一、三次握手简单例子

    A:客户端 B:服务端

    第一次握手: AB打电话说,你可以听到我说话吗?

    第二次握手: B收到了A的信息,然后对A说: 我可以听得到你说话啊,你能听得到我说话吗?  

    第三次握手: A收到了B的信息,然后说我能听到你说话,我要给你发信息啦!

    图文说明:

    第一次握手:客户端通过调用connect发起主动打开。客户端向服务器发出连接请求的TCP报文段,其TCP首部中的同步比特SYN置为1,并TCP首部中序号seq设置为x(TCP规定SYN报文段不能携带数据,但是要消耗一个序号),表明要转送数据时初始序列号是x。

    第二次握手:服务器收到数据报后,从TCP数据报首部的同步比特SYN位为1就知道这是一个建立连接的请求。服务器如果同意,会发回确认。在确认报文段中把同步比特位SYN设置为1,确认比特位ACK设置为1,由于TCP请求报文段中的序号是x,所以服务器在发送确认报文段中的确认号ack是x+1,同时把确认报文段中的序号seq设置为y,表明服务器发送数据的初始序列号为y。该报文段也不能携带数据(因为SYN=1,所以不携带任何数据)

    第三次握手:客户端收到服务器端的报文段后,要对服务器端中的SYN进行确认。在确认报文段中把确认比特位ACK设置为1,然后把确认号ack设置为y+1,自身的序号seq设置x+1。

    注:客户的初始序列号为x,服务器的初始序列号为y,那么确认报文段中的确认号ack就是所期待的对方要发送的下一个序列号

    二、四次挥手

    例子:

    A:“喂,我不说了 (FIN)。”A->FIN_WAIT

    B:“我知道了(ACK)。等下,上一句还没说完。Balabala…..(传输数据)”B->CLOSE_WAIT | A->FIN_WAIT2

    B:”好了,说完了,我也不说了(FIN)。”B->LAST_ACK

    A:”我知道了(ACK)。”A->TIME_WAIT | B->CLOSED

    图文说明:

     

    第一次挥手:假设客户端执行主动关闭,那么它会向服务器端发出释放连接的报文段,这个TCP报文段中终止比特FIN置为1,序号seq设置为u(假设上一个发的数据序号是u-1)。并停止发送数据。主动关闭TCP连接。等待服务器的确认,这里需要注意,因为TCP是全双工的,所以TCP连接上有两条数据通路,发送FIN的一端就不能发送数据,也就是关闭了其中一条数据通路,对方还是可以继续发送数据。

    第二次挥手:服务器端收到客户端的释放连接的报文段后会执行被动关闭,它要对客户端的数据报进行确认,服务器端会发送一个确认的数据报,确认比特ACK设置为1,确认号为u+1,自身的序号seq为v(假设上一个发的数据序号是v-1)。这个时候TCP处于半关闭状态,服务器依然可以向客户端发送数据(数据的序号为v+1 ~ w-1),客户端任要接受。

    第三次挥手:服务器端已经没有要发送给客户端的数据,那么服务器端也会调用close关闭套接字,这样服务器端也会发送一个FIN的TCP报文段,序号是w(假设上一个发的数据序号是w-1)。这个时候服务器端不会再向客户端发送数据了。

    第四次挥手:客户端接受到这个最终的FIN的释放连接报文段后必须对报文段进行确认。在确认的报文段中,ACK=1,确认序号ack=w+1,自己的序号seq=u+1(他的上一个序号的数据报就是申请释放连接的数据报,序号是seq=u)。

    三、TCP连接11种状态

    客户端独有的状态:SYN_SENT 、FIN_WAIT1 、FIN_WAIT2 、CLOSING 、TIME_WAIT 。

    服务器独有的状态:LISTEN 、SYN_RCVD 、CLOSE_WAIT 、LAST_ACK 。

    共有的状态:CLOSED 、ESTABLISHED 。

     

    l  SYN_SENT :这个状态与SYN_RCVD 状态相呼应,当客户端SOCKET执行connect()进行连接时,它首先发送SYN报文,然后随即进入到SYN_SENT 状态,并等待服务端的发送三次握手中的第2个报文。SYN_SENT 状态表示客户端已发送SYN报文。

    2  FIN_WAIT_1 :这个状态得好好解释一下,其实FIN_WAIT_1 和FIN_WAIT_2 两种状态的真正含义都是表示等待对方的FIN报文。而这两种状态的区别是:FIN_WAIT_1状态实际上是当SOCKET在ESTABLISHED状态时,它想主动关闭连接,向对方发送了FIN报文,此时该SOCKET进入到FIN_WAIT_1 状态。而当对方回应ACK报文后,则进入到FIN_WAIT_2 状态。当然在实际的正常情况下,无论对方处于任何种情况下,都应该马上回应ACK报文,所以FIN_WAIT_1 状态一般是比较难见到的,而FIN_WAIT_2 状态有时仍可以用netstat看到。

    3  FIN_WAIT_2 :上面已经解释了这种状态的由来,实际上FIN_WAIT_2状态下的SOCKET表示半连接,即有一方调用close()主动要求关闭连接。注意:FIN_WAIT_2 是没有超时的(不像TIME_WAIT 状态),这种状态下如果对方不关闭(不配合完成4次挥手过程),那这个 FIN_WAIT_2 状态将一直保持到系统重启,越来越多的FIN_WAIT_2 状态会导致内核crash。

    4  CLOSING :这种状态在实际情况中应该很少见,属于一种比较罕见的例外状态。正常情况下,当一方发送FIN报文后,按理来说是应该先收到(或同时收到)对方的ACK报文,再收到对方的FIN报文。但是CLOSING 状态表示一方发送FIN报文后,并没有收到对方的ACK报文,反而却也收到了对方的FIN报文。什么情况下会出现此种情况呢?那就是当双方几乎在同时close()一个SOCKET的话,就出现了双方同时发送FIN报文的情况,这是就会出现CLOSING 状态,表示双方都正在关闭SOCKET连接。

    5  TIME_WAIT :表示收到了对方的FIN报文,并发送出了ACK报文。 TIME_WAIT状态下的TCP连接会等待2*MSL(Max Segment Lifetime,最大分段生存期,指一个TCP报文在Internet上的最长生存时间。每个具体的TCP协议实现都必须选择一个确定的MSL值,RFC 1122建议是2分钟,但BSD传统实现采用了30秒,Linux可以cat /proc/sys/net/ipv4/tcp_fin_timeout看到本机的这个值),然后即可回到CLOSED 可用状态了。如果FIN_WAIT_1状态下,收到了对方同时带FIN标志和ACK标志的报文时,可以直接进入到TIME_WAIT状态,而无须经过FIN_WAIT_2状态。(这种情况应该就是四次挥手变成三次挥手的那种情况)

    6  LISTEN :表示服务器端的某个SOCKET处于监听状态,可以接受客户端的连接。

    7  SYN_RCVD :表示服务器接收到了来自客户端请求连接的SYN报文。在正常情况下,这个状态是服务器端的SOCKET在建立TCP连接时的三次握手会话过程中的一个中间状态,很短暂,基本上用netstat很难看到这种状态,除非故意写一个监测程序,将三次TCP握手过程中最后一个ACK报文不予发送。当TCP连接处于此状态时,再收到客户端的ACK报文,它就会进入到ESTABLISHED 状态。

    8  CLOSE_WAIT :表示正在等待关闭。怎么理解呢?当对方close()一个SOCKET后发送FIN报文给自己,你的系统毫无疑问地将会回应一个ACK报文给对方,此时TCP连接则进入到CLOSE_WAIT状态。接下来呢,你需要检查自己是否还有数据要发送给对方,如果没有的话,那你也就可以close()这个SOCKET并发送FIN报文给对方,即关闭自己到对方这个方向的连接。有数据的话则看程序的策略,继续发送或丢弃。简单地说,当你处于CLOSE_WAIT 状态下,需要完成的事情是等待你去关闭连接。

    9  LAST_ACK :当被动关闭的一方在发送FIN报文后,等待对方的ACK报文的时候,就处于LAST_ACK 状态。当收到对方的ACK报文后,也就可以进入到CLOSED 可用状态了

    10  CLOSED:初始状态,表示TCP连接是“关闭着的”或“未打开的”。

    11  ESTABLISHED :表示TCP连接已经成功建立。

  • 相关阅读:
    快速排序算法图文详解(模版使用)
    数据库中事务和隔离级别解析
    详解对象的创建,布局,定位,存活判断
    SpringCloud-Ribbon:认识并配置负载均衡
    SpringCloud-Feign:接口式微服务调用
    SpringCloud-Eureka(3)集群配置和了解CAP原则
    SpringCloud-Eureka(2)服务注册与信息配置
    SpringCloud-Eureka(1)认识Eureka和初步配置
    Promise
    es6
  • 原文地址:https://www.cnblogs.com/leeSmall/p/10890548.html
Copyright © 2011-2022 走看看