zoukankan      html  css  js  c++  java
  • 三次握手与四次挥手

    三次握手:

      第一次握手:

            客户端:首先客户端发起连接,在TCP层封装的包内设置标志位SYN,同时产生一个随机32位序号(举例为1000),发送给服务器端。

            服务端:服务器端接受后,首先检测标志位SYN是否为1,若为1则说明接受成功。

      第二次握手:

            服务端:服务端也往回发送一个包,在包的TCP层设置标志位ACK为1,作为对客户端请求连接发送的包的应答。同时也设置该包内的标志位SYN位上为1。服务器往回送的包的标志位已经设置完了,随后在设置32位确认序号值(注意不是32位序号值)(举例为1001),这个值是客户端请求连接所发送的包中的32位序号值+1.。设置完32位确认序号后,还要在设置一个32位序号值(举例为2000),在将这个包发送给客户端。

            客户端:接收到服务端发送的包后,首先检测ACK标志位是否为1。然后根据自己第一次握手时所发出的32位序号值检测服务端发送的包的32位确认信号值,是否相差为1。

      第三次握手:

            客户端:发送一个确认数据包,该数据包首先设置标志位ACK为1,然后将第二次握手时发送的32位序号值+1后放入32位确认序号值中(举例为2001)。

            服务端:接受到客户端的确认数据包,首先检测标志位ACK是否为1,然后校验32位确认序号值是否为第二次握手中服务端所发送的32位序号值(2000)加1后的值(2001)。

      ACK所回应32位确认序号值的意义:以1000为例,ACK为1001代表 发过来的32位序号值(1000)+SYN标志位值(1)+携带数据值(0)=1000+1+0

                       加上SYN标志位值1,是为了告诉对端,你发送的包为SYN包这一点我已知晓。

                       如果携带了数据10个字节,则应AC返回1011,即代表在32位序号值的基础上,我已经接受到了所发送的10个字节,并且检测到了SYN标志位为1。

      mss:最大数据长度,用于告诉对端,以后连接进行数据传输时所发送的数据最大值不能超过mss这个最大值。

     

    数据传输阶段:

          客户端:向服务器发送一个请求数据包,其中携带有数据。首先在这个包中设置32位序号值,该值为上一次对端发送ACK时所携带的32位确认信号值。在图里,上一次对端发送ACK是发生在第二次握手时服务端对第一次握手中,客户端所发送包的确认,该值为1001。在这里因为没有设置SYN为1,所以该值不用再+1。同时设置ACK为1,并发送一个32位确认序号值8001,从图里看,这是第一次两个端间进行数据交流,为什么还要重复在发送一个32位确认序号8001呢?这是为了服务端往客户端发送包时设置32位序号值考虑,因为服务端往客户端发送包时也要填入32位序号值,这个值也与对端上次最后发送ACK时携带的32位确认序号值相等。

          服务端:接受到客户端发送的请求数据包后,首先处理数据,然后将处理后的数据封入TCP层的数据中。然后设置32位信号值,这个值与上次最后一次对端发送ACK的32位确认信号值相等,同时设置ACK值为1,并填入32位确认序号值,这个值是上次对端发送的包的32位序号值加上所接受到的数据大小(1021:1001+接受到20个字节)的值。

          客户端:接受到服务端返回的包,首先检查32位确认序号值,这是为了检测上次发送的包的数据是否被对面接受,如果值该32位确认序号值不为1021,而为1001,则代表该部分数据都丢失了,因此需要重传一次。如果确认该值等于1021,代表接受成功。然后处理对端所发送过来的数据,这里图中有10个字节。之后需要告诉对端,客户端已经成功接受到你们所发过来的数据,返回一个数据包,设置ACK位为1,并设置32位确认信号值为8011,这代表上一个对端发送的32位信号值加上所接收到的数据大小(8011:8001+接受到10个字节)的值。

    TCP的安全性体现在此,每次数据传输,都会告诉对端自己是否已经接受到了你说封装的数据。

             

    四次挥手:

    不同于三次握手只能由客户端发起,四次挥手既可以通过客户端发起,也可以通过服务端发起。

    以客户端发起断开为例:

    第一次挥手:

        客户端:发送一个请求断开的数据包。首先设置FIN标志位为1,然后填入32位序号值,该值也是与最近一次对端发送ACK时的32位确认信号的值。在然后设置ACK为1,填入32位确认序号值,该值与上一次客户端发送的ACK中的32位确认序号值相等,只是为了让对端在往回发送数据包时填32位序号值。

    第二次挥手:

        服务端:首先校验对端发送的请求断开的数据包的FIN标志位是否为1,然后向对端发送一个ACK包,并设置32位确认序号值该值为对端所发送的请求断开数据包中,32位序号值加上1,这个加1代表FIN标志位的值,即告诉对端,你发过来的数据包是请求断开的数据包这一点我已知晓。如果客户端发送FIN包时携带了数据,该确认序号值还要加上发送的携带数据的大小。

        客户端:检测对端发送的数据包的ACK位是否为1,然后在检测32位确认序号值的大小是否满足要求。

    第三次挥手:

        服务端:服务端向对端发送一个FIN包,告诉对端我请求与你断开连接。首先设置数据包内FIN标志位为1,然后填入32位序号值,该值与上一次对端发送的ACK包的32位确认序号值相等,然后设置ACK标志位为1,填入32位确认信号值,该值与上一次对端发送的包中32位序号值加上接受到的FIN值加上所携带的数据值相等,或者说是重复上一次服务端发送的ACK值而已。

        客户端:检测数据,首先校验FIN标志位,然后检验32位序号值。然后校验ACK标志位,然后检验32位确认序号值。

    第四次挥手:

        客户端:发送一个ACK包,首先设置ACK标志位为1,然后设置32位确认序号值,该值为上一次对端发送的FIN包的32位序号值加上FIN标志位的值1在加上所携带的数据(这里为0)。

            

  • 相关阅读:
    STM32中GPIO的8种工作模式
    robots.txt与搜索引擎
    关于《腾讯工具类APP的千年老二》的读后感
    PCB布线的操作步骤
    c语言数据库编程ODBC
    锂电池相关结构优势特点及其保护电路解析方案
    C语言中的#与##字符的作用
    PADS中Layer的描述说明
    吃了单片机GPIO端口工作模式的大亏——关于强推挽输出和准双向口(弱上拉)的实际应用
    Protel与PADS之间相关文件的转换
  • 原文地址:https://www.cnblogs.com/lxy-xf/p/11006087.html
Copyright © 2011-2022 走看看