• 从序号和确认号理解TCP三次握手


    头部信息

    TCP首部存储的数据和建立连接有关,具体每个字段的用途可以参考这一篇文章,其中序号和确认号决定了发送数据的内容。

    • 头部中间部分"保留"和"窗口"中间是标志位,会携带一些连接的信息
    • 序号(Sequence Number):当前TCP数据部分的第一个字节编号(实际是一个非常大的值,非常大的值 - 固定值 = 小的编号,同一请求有一个固定值,固定在这里插入图片描述
      值来源于建立连接时seq=0时)
    • 确认号(Acknowledgment Number):ACK=1时才有效,期望对方下一次传过来的TCP数据部分的第一个字节编号

    三次握手

    建立连接的时候会有三步,也就是我们所说的三次握手。

    • SYN=1,ACK=0,序号 seq=x(连接之初的客户端固定值,简单来说就是0),没有发任何字节,所以数据长度为0,此时是客户端向服务器发送的建立连接请求。
    • SYN=1,ACK=1,序号 seq=y(连接之初的服务器固定值,简单来说就是0),确认号 ack = x+1,数据长度为0,此时是服务器向客户端发送响应,表示希望收到客户端发送第1个字节的数据。
    • SYN=0,ACK=1,序号 seq=x+1,确认号 ack=y+1,数据部分长度为0,此时客户端确认收到服务器的确认消息,建立连接完成。表示希望收到服务器第一个字节的数据。

    在这里插入图片描述

    连接时,存在一些状态的变化

    • CLOSED:client处于关闭状态
    • LISTEN:server处于监听状态,等待client连接
    • SYN-RCVD:表示server接受到了SYN报文,当收到client的ACK报文后,它会进入到ESTABLISHED状态
    • SYN-SENT:表示client已发送SYN报文,等待server的第2次握手
    • ESTABLISHED:表示连接已经建立

    抓包数据来看如下所示

    在这里插入图片描述

    疑问

    那么可能有人会问,为什么需要三次握手,两次不就可以互相确认了吗?

    三次握手的目的:防止server端一直等待,浪费资源。
    如果只有两次握手,第一次发送SYN=1时因网络延迟没发送成功,那么客户端会再发送一次SYN=1的建立请求,此时发送成功,客户端和服务器之间完成通信。
    过了一段时间,第一次发送的SYN=1消息才发送到服务器,此时服务器以为是新的建立连接过程,又会回复一个SYN=1,ACK=1的响应。
    如果只有两次连接,服务器会以为成功建立连接,但实际上客户端的数据已经获取到,不会再发送请求了,服务器就会处于一直等待的状态。
    采用三次握手就可以防止这样的情况,因为第三次请求没发送给服务器,所以它处于同步已接受状态,如果一直没有收到第三条请求则会关闭连接。

    那如果第三次握手失败了呢?

    此时server的状态为SYN-RCVD,若等不到client的ACK,server会重新发送SYN+ACK包。如果server多次重发SYN+ACK都等不到client的ACK,就会发送RST包,强制关闭连接。

    数据传输

    当获取连接后,就可以开始真正的传输数据啦

    • 服务器发送第一条请求给客户端,SYN=0,ACK=1,seq=1,ack=583,len=1280,发送数据的序号从1开始,希望对方发送数据从583字节开始。
    • 服务器发送第二条请求给客户端,,SYN=0,ACK=1,seq=1281,ack=583,len=2560,因为上一次请求发送了1280字节的数据,所以此条数据从1281开始,还没有收到客户端的数据,所以确认号仍然为583。
    • 服务器发送第三条请求给客户端,SYN=0,ACK=1,seq=3841,ack=583,len=1280,到上一次请求的数据已经发送到了1280+2560,所以此次从3841字节的数据开始。
    • 客户端回应服务器发送的请求,SYN=0,ACK=1,seq=583,ack=3841,len=0,因为服务器希望收到583字节开始的数据,所以这里序号为583,确认号为3841,希望收到对方以3841开始的数据(这里可能上一条数据还没有收到),长度为0表示只是确认收到的响应。

    在这里插入图片描述

    到这里就是完整的【建立连接】,以及发送请求流程。关于【释放连接】,会在下一篇文章中描述。

    以上就是关于 从序号和确认号理解TCP三次握手的内容 , 更多有关 前端网络协议的内容可以参考我其它的博文,持续更新中~

  • 相关阅读:
    MySQL的安装和删除
    vivo 海量微服务架构最新实践
    从零学算法41
    C++_特殊类的设计和单例模式
    并发编程的三大特性
    Java多线程-线程创建的3种方式
    如何做好项目管理?年薪百万项目大佬一直在用这11张图
    pytest常用插件使用大全
    C++this指针
    LINQ to SQL语句(10)之Insert
  • 原文地址:https://blog.csdn.net/bingbing1128/article/details/127722749