首页 > 其他分享 >TCP的三次握手过程

TCP的三次握手过程

时间:2024-05-02 17:22:23浏览次数:37  
标签:ACK 握手 SYN TCP 三次 序列号 客户端

TCP面向连接的、可靠的、基于字节流的传输层通信协议。

TCP是面向连接的协议,所以使用 TCP前必须先建立连接,而建立连接是通过三次握手来进行的。

TCP包头结构

在讲解三次握手的过程之前,我们先来看一下 TCP包的结构:
TCP包结构

TCP包头大小在大多数情况下是固定的,它通常是 20字节(不包括任何选项),但如果启用了选项,则最多可以达到 60字节。下面是 TCP包头的一般结构:

  • 源端口号(16位):表示发送方的端口号。
  • 目标端口号(16位):表示接收方的端口号。
  • 序列号(32位):用于对数据流中的字节进行编号,以便对方能够按顺序重新组装数据。
  • 确认号(32位):表示期望接收到的下一个序列号。
  • 数据偏移(4位):指示 TCP包头的长度,以 4字节为单位。因此,数据偏移的值乘以 4就是 TCP包头的总长度。这个字段也被称为 头部长度
  • 保留位(6位):保留供将来使用,目前全部为 0。
  • 标志位(6位):用于控制 TCP连接的状态,包括 SYNACKFINRSTPSHURG等。
  • 窗口大小(16位):表示发送方的接收窗口大小,用于流量控制。
  • 校验和(16位):用于验证 TCP报文的完整性。
  • 紧急指针(16位):当 URG标志被设置时,紧急指针表示紧急数据的末尾位置。
  • 选项(可选):可以包含各种选项,如最大报文段大小(MSS)、窗口缩放因子等,每个选项的大小不定。

在三次握手过程中,我们主要关注序列号确认号以及标志位中的SYNACK

三次握手过程

通常来说,服务器会开放监听端口,而客户端则主动连接这个端口,创建连接的时候,会进行三次握手,过程如下图所示:
TCP三次握手

  1. 客户端发送 SYN包到服务器,附上一个随机生成的序列号(ISN)。此时客户端处于 SYN_SEND状态。
  2. 服务器返回 SYN+ACK包到客户端,附上一个随机生成的序列号,确认号则是客户端上传的序列号+1。此时服务端处于SYN_RECV状态。
  3. 客户端返回 ACK到服务器,确认号是服务器下发的序列号+1。此时客户端处于ESTABLISHED状态,连接已建立,这个包可以顺带发一些数据。
  4. 服务端收到ACK后,也进入ESTABLISHED状态,可以收发数据。

三次握手的一个重要功能是客户端和服务端交换 ISN(Initial Sequence Number),以便让对方知道接下来接收数据的时候如何按序列号组装数据。同时也确保了服务端和客户端的收发都能正常进行。

使用 wireshark抓包工具,我们可以看到三次握手的数据:

wireshark

为什么是三次握手?不是两次、四次?

1. TCP 连接使用三次握手的首要原因,是为了防止旧的重复连接初始化造成混乱。

想像一个场景,客户端发了SYN之后宕机了,重启后又发了新的SYN。如果只有两次握手的话,当服务器收到旧的SYN之后,发送ACK给客户端,就直接进入ESTABLISHED状态,这时候就可以发数据了。

但是客户端期待的是新的SYN的序列号,发现服务端发的确认号不对应,会关闭这个连接,而服务器此时已经发了数据过来,这就造成了混乱。

而三次握手,客户端可以收到ACK之后,判断确认号,正确则返回ACK,错误则返回RST告诉服务器关闭这个连接。

使用三次握手和RST控制消息,将是否建立连接的最终控制权交给了客户端,因为只有客户端有足够的上下文来判断当前连接是否是错误的或者过期的,这也是TCP使用三次握手建立连接的最主要原因。

2. 三次握手的第二个原因,是为了交互双方的序列号。

TCP协议的通信双方,都必须维护一个序列号,用来保证数据包的有序,以及丢包时能够重发,所以这个初始化的序列号是很重要的。当客户端发SYN给服务器时,服务器需要返回ACK确认,而服务器发SYN给客户端时,客户端也需要发ACK确认,才能确保两边都有正确的序列号。服务器在发SYNACK时,可以合并成一条消息发送,所以是不需要四次握手的。

参考资料

标签:ACK,握手,SYN,TCP,三次,序列号,客户端
From: https://www.cnblogs.com/lcc9527/p/18170351

相关文章

  • 如何通过`HTTP2`实现TCP的内网穿透?
    可能有人很疑惑应用层转发传输层?,为什么会有这样的需求啊???哈哈技术无所不用其极,由于一些场景下,对于一个服务器存在某一个内部网站中,但是对于这个服务器它没有访问外网的权限,虽然也可以申请端口访问外部指定的ip+端口,但是对于访问服务内部的TCP的时候我们就会发现忘记申请了!这个时......
  • 多线程TCP的一些问题
    使用循环堵塞等待客户端连接,连接到一个就开一条线程,当用以下代码,即每次ad重新初始化后其地址作为实参进行线程的创建,结果就是当有新客户端连接,开了新线程时,旧线程看起来会被停止,实际上是因为ad用了地址而不是值作为实参,所以当新连接进来时,ad的值被更改,但地址不变,旧线程所使用的ad......
  • TCP的三次握手与四次挥手
    TCP的三次握手(建立连接)和四次挥手(关闭连接) https://www.cnblogs.com/Jessy/p/3535612.html面试官,不要再问我三次握手和四次挥手https://juejin.cn/post/6844903958624878606 (这篇写得好)三次握手和四次挥手过程中的异常处理https://blog.csdn.net/qq_34827674/article/detai......
  • C++ 实现基于TCP的聊天室
    需求以及思路客户端启动以后,需要去连接服务端,并在控制台输入消息发送到服务端,服务端收到该消息后发送给所有已连接的客户端。所以客户端需要做的事情只有两个:接收用户输入并将其发送到服务端接收服务端消息并将其显示到控制台服务端要做的事情也是两个:接待新连接上的客户......
  • XMU《计算方法》实验一 三次样条插值算法
    实验一 三次样条插值算法一、Matlab代码clear;x=input('请输入插值结点的x:');y=input('请输入插值结点的y:');[x,I]=sort(x);y=y(I);iflength(y)~=length(x)error('x和y的数量不相等!');endn=length(x)-1;N=n*4;%函数值约束A=[];......
  • 题解:P10329 [UESTCPC 2024] Add
    Add题意将序列进行一系列的操作,输出对\(a_{1}\)的期望值。题目中操作说的比较明了,再次就不特殊声明了。思路据题意所知,每一个\(n\)应该对应了一个固定的答案。于是我就想到可以打表,就打出了下面的式子。n=1时ans=1n=2时ans=5n=3时ans=14n=4时ans=30n=5时ans=5......
  • 后端每日一题 1:说一下三次握手
    本文首发于公众号:腐烂的橘子三次握手的流程第1步-初始连接请求SYN(Synchronize)服务端状态LISTEN,客户端向服务端发送一个SYN标志位的报文段(TCPsegment)这个报文段包含初始序列号x,以及最大报文段大小等字段客户端发送报文后,状态设置为SYN_SEND第2步-服务端回......
  • C# Modbut TCP 读写
    一、封装基本连接、读写。读写 ReadHoldingRegisters,当前有四种方案,现在只使用 ReadHoldingRegistersint类型,需要其他方案自行新增。publicclassModbusClient{privateTcpClient?tcpClient;privateIModbusMaster?modbusMaster;......
  • 1.关于Modbus TCP/RTU协议
    一、上位机C#与PLC通信1.通常情况下,需要与 PLC 工程师进行对接,并根据其编写的 PLC 程序去读写指定的寄存器。(PLC工程师提供地址表,然后C#通过Modbus读写寄存器或线圈开关)2.PLC 工程师负责编写 PLC 控制程序,其中定义了各个寄存器的功能和用途,以及与外部设备的交互逻辑。因此......
  • 三次握手与四次挥手
    三次握手握手前双方都处于close态服务器主动监听进入LISTEN状态假设客户端要建立连接第一次握手客户端随机初始化序号client_isn发送SYN报文进入SYN-SENT状态第二次握手服务端接收SYN报文后随机初始化序号序号server_isn把确认应答填为client_isn+1开启SYN和......