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)。

            

  • 相关阅读:
    leetcode 13. Roman to Integer
    python 判断是否为有效域名
    leetcode 169. Majority Element
    leetcode 733. Flood Fill
    最大信息系数——检测变量之间非线性相关性
    leetcode 453. Minimum Moves to Equal Array Elements
    leetcode 492. Construct the Rectangle
    leetcode 598. Range Addition II
    leetcode 349. Intersection of Two Arrays
    leetcode 171. Excel Sheet Column Number
  • 原文地址:https://www.cnblogs.com/lxy-xf/p/11006087.html
Copyright © 2011-2022 走看看