首页 > 其他分享 >深入浅出TCP协议

深入浅出TCP协议

时间:2024-01-18 09:45:10浏览次数:23  
标签:协议 重传 报文 深入浅出 确认 TCP 发送 客户端

TCP(Transmission Control Protocol,传输控制协议)的最终目的是为数据提供可靠的端到端的传输。它能够处理数据的顺序并恢复错误,并且最终保证数据能够到达目的地。

一、TCP协议的报头

1、源端口(Source Port):16bit(2Byte),范围:0~65535。

2、目的端口(Direction Port):16bit(2Byte),范围:0~65535。

源端口号和目的端口号都是上层应用程序的进程号。服务端提供的服务监听的端口号一般是在(1~1024),比如:http的Web服务(80),https的Web服务(443),SMTP简单邮件传输服务(25),FTP文件传输协议(21)。客户端访问服务器的客户端软件一般使用(1025~65535)的随机临时端口号。

3、序号(Sequence Number):32bit(4Byte),范围:0~4,294,967,295。一次TCP通信(从TCP连接的建立到断开)过程中某一个传输方向上的字节流的每个字节的第一个编号。例如,一段报文的序号字段值是 1 ,而携带的数据共有100字段,显然下一个报文段(如果还有的话)的数据序号应该从101开始。

4、确认号(Acknowledge Number):32bit(4Byte),范围:0~4,294,967,295。对收到的报文进行确认,是期望收到对方下一个报文的第一个数据字节的序号。例如,B收到了A发送过来的报文,其序列号字段是501,而数据长度是200字节,这表明B正确的收到了A发送的到序号700为止的数据。因此,B期望收到A的下一个数据序号是701,于是B在发送给A的确认报文段中把确认号置为701。

5、数据偏移(Header Length):4bit(2Byte),范围:0~15,表示TCP头部的长度。数据偏移的单位为4字节[其实每个1代表4字节,例如,首部长度如果是20字节,那么这里就是0101(即:5)]。由于4位二进制数能表示的最大十进制数是15,因此数据偏移的最大值是60字节(固定首部20字节 + 选项40字节)。

6、保留(Reserved):6bit,保留为今后使用,目前都置为0。

7、标志位(Control bit):6bit,控制位。

  • URG(URGent):1bit,紧急,URG=1,表示紧急指针字段有效。(表示发送方插队处理)
  • ACK(ACKnowlegement):1bit,确认位,仅当ACK=1,确认号字段才有效。当ACK=0时,确认号无效。TCP规定,在连接建立后,所有传输的报文段都必须把ACK置为1。
  • PSH(PuSH):1bit,推送,当两个应用进程进行交互通信时,有一段的应用进程希望在键入一个命令后立即就能收到对方的响应。(表示接收方插队处理)
  • RST(ReSeT):1bit,复位,当RST=1时,表明TCP连接中出现严重差错。例如,由于主机崩溃或其他原因,必须释放连接,然后再重新建立连接。
  • SYN(SYNchronization):1bit,同步。在连接建立时用来同步序号。当SYN=1,ACK=0时,表明这是一个连接请求报文段,对方若同意建立连接,则应在响应报文段中使SYN=1,ACK=1。因此,SYN置为1就表示这是一个连接请求或连接接受报文。
  • FIN(FINish):1bit,终止。用来释放一个连接。当FIN=1时,表示此报文段的发送方的数据已经发送完毕。并要求释放传输连接。

8、窗口(Window):16bit(2Byte),范围:0~65535。TCP协议有流量控制功能,窗口值用来告诉对方。

9、校验和(Checksum):16bit(2Byte),校验和。检验和字段检验的范围包括首部和数据这两部分。

10、紧急指针(Urgent):16bit(2Byte),紧急指针。紧急指针仅在URG=1时才有意义,它指出本报文段中的紧急数据的字节数(紧急数据结束后就是普通数据)。

11、选项(Options):长度可变,最长可达40Byte。当没有使用选项时,TCP的头部长度是20Byte。

  • 种类(Kind):每一个选项的头一节点为“种类”,指明了该选项的类型
  • 长度(Length):需要记住的是TCP头部的长度应该是32比特的倍数,因为TCP头部长度字段是以此为单位的
  • 信息(info):是选项的具体信息

 

kind=0:选项表结束选项。

kind=1:空操作(nop)选项。没有特殊含义,一般用于将TCP选项的总长度填充为4字节的整数倍

kind=2,length=4:最大报文长度选项(MSS,Max Segement Size)。TCP连接初始化时,通信双方使用该选项来协商最大报文段长度。TCP模块通常将MSS设置为(MTU-40)字节(减去的40字节包括20字节的TCP头部固定字段和IP头部固定字段),从而避免本机发生IP分片,对以太网而言,MSS值是1460

kind=3,length=3:窗口扩大因子选项。TCP连接初始化时,通信双方使用该选项来协商接收通告窗口的扩大因子。在TCP头部中,接收通告窗口大小时使用16bit表示的,故最大为65535字节,但实际上TCP模块允许的接收通告窗口大小远不止这个数(为了提高TCP通信的吞吐量)。窗口扩大因子解决了这个问题。

kind=5,length=2:SACK实际工作的选项。该选项的参数告诉发送方本端已经收到并缓存的不连续的数据块,从而让发送端可以据此检查并重发丢失的数据块。

kind=8,length=10:时间戳选项。该选项提供了较为准确的计算通信双方之间的回路时间(Round Trip Time,RTT)的方法,从而为TCP流量控制提供重要信息。

 

二、TCP连接的建立——三次握手

在握手之前,主动打开连接的客户端结束Close阶段,被动打开的服务器也结束CLOSE阶段,并进入Listen阶段。随后进入三次握手阶段:

1、首先客户端向服务器发送一个SYN包,并等待服务器确认

  • 标志位为SYN,表示请求建立连接
  • 序号为Seq = x(x一般为1)
  • 随后客户端进入SYN-SENT状态

2、服务器接收到客户端发来的SYN包后,对该包进行确认后结束Listen阶段,并返回一段TCP报文

  • 标志位为SYN和ACK,表示确认客户端的报文Seq序号有效,服务器能正常接收到客户端发送的数据,并同意创建新连接
  • 序号为Seq = y
  • 确认号为Ack = x + 1,表示收到客户端的序号Seq并将其值加1作为自己的确认号Ack的值,随后服务器进入SYN-RECV状态

3、客户端接收到服务器发送的SYN + ACK包后,明确了从客户端到服务器的数据传输是正常的,从而结束SYN-SENT状态。并返回最后一段报文

  • 标志位为ACK,表示确认收到服务器同意连接的信号
  • 序号为Seq = x + 1,表示收到服务器的确认号Ack,并将其值作为自己的序号值
  • 确认号为Ack = y + 1,表示收到服务器的序号Seq,并将其值加1作为自己的确认号Ack的值
  • 随后客户端进入ESTABLISHED状态

当服务器收到来自客户端确认收到服务器数据的报文后,得知从服务器到客户端的数据传输正常的,从而结束SYN-SENT状态,进入ESTABLISHED状态,从而完成3次握手

 

三、TCP连接的拆除——四次挥手

这里假设客户端主动释放连接。在挥手之前主动释放连接的客户端结束ESTABLISHED状态,随后开始四次挥手阶段:

1、首先客户端向服务器发送一段TCP报文表明其想释放TCP连接

  • 标记位为FIN,表示请求释放连接
  • 序号为Seq = u
  • 随后客户端进入FIN-WAIT-1阶段,即半关闭阶段,并且停止向服务器发送通信数据

2、服务器接收到客户端请求断开连接的FIN报文后,结束ESTABLISHED状态,进入CLOSE-WAIT状态并返回一段TCP报文

  • 标记位为ACK,表示接收到客户端释放连接的请求
  • 序号为Seq = v
  • 确认号为Ack = u + 1,表示是在收到客户端报文的基础上,将其序号值加1作为本段报文确认号Ack的值
  • 随后服务器开始准备释放服务器到客户端方向的连接

客户端收到服务器发送过来的TCP报文后,确认服务器已经收到了客户端连接释放的请求,随后客户端进入FIN-WAIT-2状态

3、服务器在发出ACK确认报文后,服务器会将遗留的带穿数据发送个客户端,待传输完成后即进入CLOSE-WAIT状态,便做好了释放服务器到客户端的连接准备,再次向客户端发出一段TCP报文

  • 标记为FIN和ACK,表示已经准备好释放连接了
  • 序号为Seq = w
  • 确认号为Ack = u + 1,表示在收到客户端报文的基础上,将其序号Seq的值加1作为本段报文确认号Ack的值

随后服务器结束CLOSE-WAIT状态,进入LAST-ACK状态,并且停止向客户端发送数据

4、客户端收到从服务器发来的TCP报文,确认了服务器已经做好释放连接的准备,于是进入TIME-WAIT状态,并向服务器发送一段TCP报文

  • 标记位为ACK,表示接收到服务器准备号释放连接的信号
  • 序号为Seq = u + 1,表示是在己经收到服务器报文的基础上,将其确认号Ack值作为本段报文序号的值
  • 确认号为Ack = w + 1,表示是已经在收到服务器报文的基础上,将其序号Seq的值加1作为本段报文确认号Ack的值

随后客户端开始在TIME-WAIT状态等待2 MSL,服务器收到从客户端发出的TCP报文之后进入CLOSED状态,由于正式确认关闭服务器到客户端方向上的连接,客户端等待完 2 MSL之后,进入CLOSED状态,由此完成四次挥手

 

四、TCP如何保证可靠传输

发送确认机制

TCP报文头中有两个字段:

  • [Sequence Number]序列号:表示发送数据的起始号
  • [Acknowledgment Number]确认号:表示消息已经接收,返回下次要发送的起始号

发送确认

TCP每次发送数据,都有一个确认应答ACK,表示已经收到了数据包。确认号表示下一个传送的起始号

 发送一个http请求,使用Wireshark抓取数据包,打开 统计 -> 流量图,在弹出的页面上将Flow Type修改成 TCP Flows,就能看到TCP的数据包请求

上图中标记的三个地方,中间的标记的“发送确认”,就表示数据发送和应答,len表示字节长度。发送1~218的字节,确认应答返回了确认号219,第二个发送确认也是类似原理,有所不同的是这个发送确认时接收端的发送确认。

重传机制

发送端的数据包,一般都发送到接收端。但是在网络不好,或者信号比较差的情况下,可能就无法正常发送到数据。

先介绍两个概念:[RTT] 和 [RTO]

[RTT] Round-Trip Time表示往返时间,表示网络一端到另一端所需要的时间,也就是数据包往返时间,以TCP握手为例:

 RTT表示数据包从发送到收到确认应答的时间。

[RTO]Retransmission Timeout表示超时重传时间。超过这个时间没有确认应答,就会重传报文段,这个时间根据RTT来设置的。

重传机制是 TCP 基本的错误恢复功能,常见的重传机制有两种:

  • 超时重传
  • 快速重传

超时重传

超时重传就是超过规定的时间没有收到确认消息,就会再次发送一个消息请求。TCP发送方发送报文时,会设置一个定时器,如果在时间范围内没有收到接收方发来的ACK确认报文,发送方就会重传已经发送的报文段

TCP有两种超时重传的情况:

  • 报文在发送途中丢失
  • 确认包在途中丢失

上面的 RTO 表示超时重传时间,RTO 的设定不能过大的或者过小:

  • 如果过大,请求等待的时间过长,请求的效率低。
  • 如果过小,正常返回的确认还未来得及返回,就重传。加大网络符合。

设置一个适当的RTO才会让重传机制更加高效。超时时间RTO应该略大于往返时间RTT

如果超时重传的报文段又超时了该怎么办呢?,答案就是「重传的超时时间加倍」,也就是再次超时重传的超时时间会增加到之前的两倍。

如果超时重传的报文段又丢包呢?此时发送方会以 RTO 时间的 2、4、8倍的倍数尝试多次重传。

快速重传

快速重传不会等待超时时间到了再重传,发送方收到3次重复确认报文,就不会等超时时间重试,而是直接重传报文。

连续发送的报文段,中间只要有一个丢失,后续返回的确认号都是相同的,后面的报文段无论有没有返回,都会重传一遍,这种设置还是比较合理的。在一段时间内,如果网络状况不好,导致丢包情况,后续的报文段一般也会丢包。

但是重传丢包后面所有的包,也会造成网络传输的浪费。对于上面的例子,如果只想传输Seq2,其他有返回的确认包就不用重传。

TCP有一种重传机制:SACK Selective Acknowledgment选择性重传

这种方式需要 TCP 报文段选项加一个 SACK 字段,使用查看 Wireshake SYN 包中 SACK Permitted:

发送包有返回确认应答,就会发送给发送方告知对应的数据被接收了,发送方就能记录哪些数据被接收了,哪些数据没有被接收。后面只会重传没有被接收到的数据包,这就是选择性重传。

滑动窗口

TCP发送比较大的数据包,TCP会一次性发送大的数据包给接收方?答案是不会的,需要考虑网络带宽,TCP会将大的数据包拆分成多个大小适中的数据包,发送一个http请求,添加较大的参数,使用Wireshark抓取数据包

 数据包被拆分成5个小的数据包。

数据包被拆分成多个小的数据包之后,数据包发送都有返回一个确认序列号,每次发送一个新的包,都等待上一个包的ACK回来之后才能发送,这个一来一回的效率很低:

TCP为了解决这个问题,引入 窗口 的概念,在窗口范围内的数据包,无需等待上一次ACK确认,可以直接发送数据包:

滑动窗口是 TCP 协议中的一种流量控制机制,用来控制发送方和接收方数据传输的速率,避免数据过多造成数据无法及时处理。

窗口的大小也就是 TCP 报文段的 windos 字段,表示的就是接收方目前能接收的缓冲区的剩余大小,发送端根据这个字段处理发送的数据。

发送端的窗口

发送窗口根据三个标准来划分:是否发送、是否收到ACK,是否在接收方处理范围内,分成了四个部分:

四个部分组成:

  • 第一部分是已经发送并收到ACK确认的数据,这部分数据已经发送成功了,无需在缓存中保留了
  • 第二部分数据是已经发送但是未收到ACK确认的数据
  • 第三部分数据是未发送,但是在接收处理范围之内的数据。第二、第三部分共同组成发送的窗口
  • 第四部分是需要发送,但是未在接收范围之内的数据,这部分数据在没有接收ACK确认之前,是不会发送数据的

如果发送方一直没有收到ACK,数据不断的发送,很快可用窗口也被耗尽,这时发送方也不会继续发送数据了,这时发送端可用窗口为零的情况我们称为“零窗口”

 随着ACK的确认,窗口也会依次向右滑动,比如发送端的窗口中,比如40~43字节都受到了ACK确认,那么整个可用的窗口就会顺次往右移动。此时53~57的数据也都能发送了。

接收端的滑动窗口相对发送端的窗口要简单的多,主要分为三个部分

  • 已经接收并确认的数据
  • 可以接收但是未接收的数据
  • 在接收范围之外(不够缓存的数据),也就是不可以接收的数据

但数据接收后,窗口也向右边滑动,给发送端的数据提供数据缓存。如果读取缓存的数据速度有变化时,接收端可能也会改变接收窗口的大小,以此来控制发送端的发送速度,这就是滑动窗口进行流量控制的一种机制。

拥塞控制

网络中由于有大量的包传输,在固定带宽下处理不过来数据包的传输,可能会导致数据包阻塞,网络传输的速度下降,甚至会下降到 0 的情况。这就有点类似排队买东西,如果正常排队,速度虽然不快但处理速度比较稳定。但是如果一下涌来很多人,就会处理不过来,导致「堵死情况」。 而 TCP 被设置成一个无私的协议,当遇到网络拥塞时,TCP 会减少自己发送数据包,这样网络拥塞会得到很大的缓解。

为了实现拥塞控制,首先在发送端定义一个拥塞窗口 CWND (congestion window),「限制发送端发送数据最多没有收到 ACK 确认包的大小,超过拥塞窗口范围后,就不会继续发送数据了」。

拥塞窗口会随着网络情况的变化动态的调用自身的大小,大体的变化规则是:如果没有出现拥塞,就扩大窗口大小,否则就缩小窗口的大小

拥塞控制算法主要包含四个部分:

  • 慢启动
  • 拥塞避免
  • 拥塞发生
  • 快速恢复

慢启动

当一个新的TCP连接开始时,无法确定是否用拥塞发生,一开始不会发送大量的包,而是从最小的发送窗口开始,后续会采用倍增的方式增加窗口的大小,窗口大小从 1 开始,后续慢慢增大到 2、4、8 等。

指数增加速度会越来越快,窗口扩大的一定的程度,就会减慢增加的速度,改成线性增加,这时候就进入拥塞避免阶段。

拥塞避免

慢启动和拥塞避免的临界点叫做 慢启动门限(sshthresh,slow start threshold)

cwnd < ssthresh时,使用慢启动算法

cwnd >= ssthresh时,就会使用拥塞避免算法

ssthresh大小一般是65535字节。拥塞避免的规则:每当收到一个ACK时,cwnd + 1 / cwnd。就变成线性增长了。

拥塞发生

拥塞避免将原来的指数增长改成线性增长,虽然增长速度减慢,但CWND窗口还是在增长阶段。随着窗口进一步缓慢增加,网络还是会遇到阻塞的状态,会出现丢包的情况。就需要对丢包进行重传。

重传机制有两种:

  • 超时重传
  • 快速重传

当发生超时重传时,sshthresh和cwnd的值会发生如下变化:

  1. sshthresh 变成 cwnd 的一半
  2. cwnd重置为1

cwnd重置为1,表示直接进入慢启动状态。

上面的超时重传速度变化太快,而快速重传是一个相对温和的方案。如果我们连续 3 次收到同样序号的 ACK,包还能回传,说明这个时候可能只是碰到了部分丢包,网络阻塞还没有很严重,无需重置 cwnd。

此时sshthresh和cwnd变化如下:

  1. cwnd = cwnd / 2,也就是设置为原来的一半
  2. sshthresh = cwnd

并进入到快速恢复阶段

快速恢复

快速恢复主要是将 cwnd 恢复到正常大小,上面说的 cwnd 设置成原来的一半,ssthresh 设置成 cwnd 的大小。

快速恢复算法如下:

  1. 重传丢失的数据包
  2. 如果接收到重复ACK确认,cwnd增加1
  3. 如果接收到新数据的 ACK 确认,就将 ssthresh 恢复到慢启动时期的值,因为返回新数据的 ACK 确认,表示网络阻塞已经结束,可以恢复到之前的状态,cwnd 也可以指数或者线性增加。

 

标签:协议,重传,报文,深入浅出,确认,TCP,发送,客户端
From: https://www.cnblogs.com/hongliang888/p/17967413

相关文章

  • 42 干货系列从零用Rust编写负载均衡及代理,wmproxy中配置tcp转websocket
    wmproxywmproxy已用Rust实现http/https代理,socks5代理,反向代理,静态文件服务器,四层TCP/UDP转发,七层负载均衡,内网穿透,后续将实现websocket代理等,会将实现过程分享出来,感兴趣的可以一起造个轮子项目地址国内:https://gitee.com/tickbh/wmproxygithub:https://github.com/......
  • 两种实现TCP并发的方式
    【一】socketserver模块实现TCP并发服务服务端importsocketserverclassRequesterHandle(socketserver.BaseRequestHandler):defhandle(self)->None:print(self.request)print(self.client_address)#self.request相当于TCP协议的conn......
  • DHCP协议
    DHCP协议做个简单小实验先配置基础网络然后配置dhcpservicedhcp开启服务ipdhcppoolvlan10配置地址池network10.1.1.024网段default-router10.1.1.1网关dns-server172.16.10.1dnslease08ip地址租期代表租期时间为8天ipdhcpexcluded-address10.1.1.......
  • 使用nginx代理emqx的TCP、WS、WSS连接请求
    项目代理关系: 注:主机上已存在名为:nginx-proxy的一级nginx的代理,将监听了主机的80、443端口docker-compose.ymlversion:"3.7"services:emqx:image:emqx/emqx:4.4.18restart:unless-stoppedcontainer_name:emqxenvironment:EMQX_ADMI......
  • 22.多协议封装设计
    多协议封装应用场景 问题:响应值不统一jsonxml断言比较困难解决方案:获得的响应信息全部转换为结构化的数据进行处理解决方案 participant请求asreqparticipant响应asresparticipantxml_响应asxml_resparticipant其他格式的响应asjs......
  • TCP 拥塞控制对数据延迟的影响
    哈喽大家好,我是咸鱼今天分享一篇文章,是关于TCP拥塞控制对数据延迟产生的影响的。作者在服务延迟变高之后进行抓包分析,结果发现时间花在了TCP本身的机制上面:客户端并不是将请求一股脑发送给服务端,而是只发送了一部分,等到接收到服务端的ACK,然后继续再发送,这就造成了额外的RTT......
  • 网络编程之TCP协议的三次握手和四次挥手
    引言见过比较典型的面试场景是这样的:面试官:请介绍下三次握手求职者:第一次握手就是客户端给服务器端发送一个报文,第二次就是服务器收到报文之后,会应答一个报文给客户端,第三次握手就是客户端收到报文后再给服务器发送一个报文,三次握手就成功了。面试官:然后呢?求职者:这就是三次......
  • 网络编程之基于TCP协议的socket套接字编程
    基于TCP的套接字【1】方法简介tcp是基于链接的必须先启动服务端然后再启动客户端去链接服务端tcp服务端server=socket()#创建服务器套接字server.bind()#把地址绑定到套接字server.listen()#监听链接inf_loop:#服务器无限循环conn=serv......
  • 网络编程之基于UDP协议的socket套接字编程
    基于UDP的套接字udp是无链接的,先启动哪一端都不会报错【1】方法简介(1)UDP服务端server=socket()#创建一个服务器的套接字server.bind()#绑定服务器套接字inf_loop:#服务器无限循环conn=server.recvfrom()/conn.sendto()#对话(接收与发送)serv......
  • 网络编程TCP UDP
    网络编程(1)什么是网络编程网络编程是指通过编程语言在计算机之间建立通信的一种方式。它是在互联网上进行数据传输的关键组成部分,使计算机能够相互通信、交换信息和共享资源。网络编程涉及许多不同的技术和协议,包括TCP/IP(传输控制协议/因特网协议),HTTP(超文本传输协议),FTP(文件传......