网络-运输层

UDP

udp检验和

TCP

1,数据格式

固定长度为20字节,选项部分最多40字节

我方这一次发送的信息中,seq序号为对方上一次发送的ack序号,ack序号为上一次对方发送的seq序号+报文段大小。

同时注意一个概念  标识号:为申请连接时的seq值,同一个标识号能代表是同一个请求的数据

seq相对序号(tcp中没有,能算出来)=seq原本序号-标识号

选项可选SACK,selective ack,最多可记录四个收到的段

有些资料说tcp的保留占3位,标志占9位

其实现在标志本来占9位,但前3位基本不用

所以在学校教材说标志占6位

标志位:

1)URG:此标志表示TCP包的紧急指针域(后面马上就要说到)有效,用来保证TCP连接不被中断,并且督促中间层设备要尽快处理这些数据;

(2)ACK:此标志表示应答域有效,就是说前面所说的TCP应答号将会包含在TCP数据包中;有两个取值:0和1,为1的时候表示应答域有效,反之为0;

(3)PSH:这个标志位表示Push操作。所谓Push操作就是指在数据包到达接收端以后,立即传送给应用程序,而不是在缓冲区中排队;

(4)RST:这个标志表示连接复位请求。用来复位那些产生错误的连接,也被用来拒绝错误和非法的数据包;

(5)SYN:在建立连接是使用,用来同步序号。SYN标志位和ACK标志位搭配使用,请求连接的时候,SYN=1,ACK=0;回复连接的时候,SYN=1,ACK=1;这个标志的数据包经常被用来进行端口扫描。扫描者发送一个只有SYN的数据包,如果对方主机响应了一个数据包回来,就表明这台主机存在这个端口;但是由于这种扫描方式只是进行TCP三次握手的第一次握手,因此这种扫描的成功表示被扫描的机器不很安全,一台安全的主机将会强制要求一个连接严格的进行TCP的三次握手;

(6)FIN:表示发送端已经达到数据末尾,也就是说双方的数据传送完成,没有数据可以传送了,发送FIN标志位的TCP数据包后,连接将被断开。这个标志的数据包也经常被用于进行端口扫描。当一个FIN标志的TCP数据包发送到一台计算机的特定端口,如果这台计算机响应了这个数据,并且反馈回来一个RST标志的TCP包,就表明这台计算机上没有打开这个端口,但是这台计算机是存在的;如果这台计算机没有反馈回来任何数据包,这就表明,这台被扫描的计算机存在这个端口。

补充几个时间概念:

RTT  Round-Trip time 报文段的往返时间

RTO retransmission time-out 超时重传时间,根据RTT计算得出

MSL报文段最长生存时间,每个tcp的具体实现都必须设定MSL,RFCC 1122建议设为两分钟

2,建立连接——三次握手

通过理解了可靠传输之后,才能学习两台机器间是如何通过tcp协议进行通信的

前面说到,tcp是面向连接的,因此利用tcp协议通信时需先建立连接,下面我就来探讨如何建立连接

请注意tcp报文格式中的SYN,ACK,序号seq,确认号ack

3,可靠传输

  • 可靠传输的基本机制

可靠传输是利用ARQ协议实现的

而ARQ是建立在 确认和重传的机制的基础上的 

确认机制,即:对于接收方而言,收到数据后无论该数据是否重复,我都得发送确认信息(这样会导致发送方接受到多条确认信息,但没关系,发送方只处理超时重传时间内的确认信息,其他确认信息只接受不做任何处理,所以无影响)

重传机制,即:对于发送方而言,只要我未在超时重传时间内接收到确认信息,我就一直重发数据(这样会导致接收方收到多条重复信息,但没关系,接收方一旦发现有重复的数据便会丢弃,但会回复确认信息)

这俩个机制就保证了tcp的可靠传输,使其无差错(通过计算校验和),不丢失(未收到确认就一直重传),不重复(重复数据的就丢弃)

以这俩种机制为规定的协议即称为ARQ协议(Automatic Repeat Request),自动重传请求

连续ARQ协议

但上述方式有一定的缺陷,即:每 实现成功的传输一个包,就需要发送一个确认,开销太大,

于是引进了窗口window,wnd 的概念,窗口以字节为单位,一个窗口 囊括多个包,只需对每一个窗口回复确认信息,极大减少了回复确认信息的开销。利用ARQ技术+滑动窗口,服务器端收到多个包,只用回复一个包,核心内容为ACK(标志位)+ack(确认号)。这就是连续ARQ协议。

  • 可靠传输的实现

前面我们已经说到了如何保证数据不丢失,不重复

那么如何保证数据是有序的呢?

实际上,在应用层将数据交给运输层后

首先,运输层会对其进行拆分 ——(因为数据链路层规定每个数据包不得大于1500字节,因此需要对数据进行拆分。但为什么一定要在运输层进行拆分呢?不能在网络层,数据链路层拆吗?是因为,只有运输层有可靠传输协议,在运输层拆解的话每个segment都能带上tcp的表头,如果发生数据丢失的情况,只需重传那应该segment就ok了,但若在网络层数据链路层拆解,这两层又没有可靠传输的协议,若发生数据丢失的情况,只能利用tcp协议,但由于未在tcp分段,因此只能重传整个数据) 

然后,会对数据以字节为单位编号,接收方收到一个窗口大小的数据后便会回复一份确认信息,这份信息内容包含ACK=1,ack序号,这个ack序号为按序号收到的数据中的最高序号+1。

例如下图,swnd大小为20,那么接收方在收到20个窗口大小的数据后,便会回复一次确认信息

若完整接受到了序号为31-50的数据,那么回复的ack序号则为50+1,51

若未完整且按序的收到全部信息,如下图32,33未按序收到,那回复的ack序号则为收到的数据中的最高序号+1

这里也就是31+1。(tcp可添加选项sack,最多可回复四个未收到或未按序收到的序号,应用sack时则ack序号应为 收到的数据的序号再补上sack选项中的序号之后的最高序号)

4,流量控制:

流量控制就是接收方通过设置cwnd(接收窗口)大小,来控制发送方的swnd(发送窗口)大小,以此来控制发送方的发送速率。

一般都希望数据能传输得越快越好,但是如果发送方把数据发送得过快,接收方可能就来不及接受到所有的数据,中间可能会丢失数据报。这是为什么呢?这是由于接收数据时,需要将数据放入缓存,再将数据从缓存中提交给应用程序,发送数据时也需要将数据从应用程序转到缓存中,这个过程需要时间。

因此设计了窗口来控制每次最多接受的量(避免缓存堵塞),窗口的单位为字节(注意将窗口最小单元与报文段区分开),有rwnd,receive window 接受窗口,swnd,send window 发送窗口,cwnd congestion拥塞窗口(应用于拥塞控制)。其中swnd由接受窗口大小和拥塞窗口大小决定的,大小为min(rwnd,cwnd)  。所以能通过cwnd来控制发送方的发送窗口大小,从而控制发送方的发送速率。

因此所谓的流量控制,主要是针对接收方的,就是因为接收方缓存(接受数据的容器)容量不够用了,接收方通过设置接受窗口的大小来实现对流量的控制

窗口,应用程序和缓存的关系:

5,拥塞控制:

拥塞控制性质与流量控制不一样:

拥塞控制主要是解决由于网络堵塞导致数据传输慢的问题,而流量控制是解决接收方缓存不够导致的 数据堆积被丢弃问题

发送端的swnd代表发送数据的多少,其是由rwnd和cwnd共同决定的,前面讲了rwnd的调整,现描述cwnd的调整规则

四点针对cwnd调整的规定:

首先需目明白快恢复和快重传是为了避免接收方将意外丢包识别为网络堵塞(一旦错误识别便会执行慢开始,影响速度)

1,慢开始:cwnd设为初始值1(这里用1代替,实际上需要通过计算得知),然后按指数级别增长(以一个往返时延为单位)sstresh(slow start threshhold)设为初始值peak

2,拥塞避免:当cwnd达到sstresh时,增长方式改为加法增长(线性增长)

3,快恢复:则sstresh减半,cwnd设为更新后的sstresh值

4, 快重传:我觉得不属于对cwnd的调整,而是为了进行快恢复而设定的一种信号):快重传是要求接收方不要等待自己发送对于窗口的确认信息才捎带有数据丢失,而是立马对丢失的数据发送三次重复的确认。

当接收方发现丢了一个中间包的时候,发送三次前一个包的 ACK,于是发送端就会快速地重传,不必等待超时再重传。

a:慢开始
慢启动阶段思路是不要一开始就发送大量的数据,先探测一下网络的拥塞程度,也就是说由小到大逐渐增加拥塞窗口的大小,在没有出现丢包时每收到一个 ACK 就将拥塞窗口大小加一(单位是 MSS,最大单个报文段长度),每轮次发送窗口增加一倍,呈指数增长,若窗口大小达到ssthresh或出现丢包时,进入拥塞避免阶段;
b:拥塞避免和快重传
当窗口达到慢启动阈值或出现丢包时,进入拥塞避免阶段,窗口每轮次加一,呈线性增长;当收到对一个报文的三个重复的 ACK 时,认为这个报文的下一个报文丢失了,进入快重传阶段,要求接收方在收到一个失序的报文段后就立即发出重复确认(为的是使发送方及早知道有报文段没有到达对方,可提高网络吞吐量约20%)而不要等到自己发送数据时捎带确认;
c:快恢复
快重传完成后进入快恢复阶段,将慢启动阈值修改为当前拥塞窗口值的一半,同时拥塞窗口值等于慢启动阈值,然后进入拥塞避免阶段,重复上述过程
————————————————
原文链接:https://blog.csdn.net/qq_48508278/article/details/122655792

两种丢包的情况对应的处理机制

1,网络堵塞,根本收不到确认信息,于是会执行慢开始(图中序号2)

2,若发送方收到3个重复确认(一共会有四个重复的,有3个是重复多余的,称为重复确认),则会执行快重传和快恢复  (图中序号3)

这篇文章讲的很好:

拥塞控制(详解)-CSDN博客

6,断开连接——四次挥手

这里假设A为请求断开连接的一方,B为接受的一方

第一次挥手:

A发出断开请求

FIN设为1,seq前面已经传送过的数据的最后一个字节的序号+1,假设为u

第二次挥手:

B发出ACK确认信息,表示我已经收到你的断开请求了,但请稍等,现在还不能断联,等我把剩下的数据传给你再断开(ack为u+1,seq为之前传送过的数据的最后一个字节的序号+1,假设为v)

第三次挥手:

依然是由B发出,此时B已经把剩余的数据传过去了,于是向A发出FIN确认信息(FIN设为1,ACK设为1,ack依然为u+1(代表依旧是对第一次挥手的确认),seq为前面发送的数据的最后一个字节的序号+1,假设为w(因为前面又发送了一些数据,所以不一定是v+1))

第四次挥手:

A收到B的FIN确认信息后,向B发送一个确认信息(ACK设为1,ack为w+1,seq为u+1),并且立马开始计时,等待2MSL(2个最长报文段寿命)后Aclose,而B在收到确认信息后,立马就close了。

面试问题:

建立连接时三次握手,为什么要进行第三次的握手?

TCP三次握手是建立TCP连接时的一种协议,确保通信双方的可靠性和正确性。具体来说,为什么要进行第三次握手呢?

  1. 建立双向通信: 第一次握手是客户端向服务器端发送连接请求,服务器端接收到请求后,会发送确认信息,表示已经收到了请求,准备接受连接。第二次握手是服务器端向客户端发送确认信息,表示已经准备好接受连接。这时候,客户端收到了确认信息,就知道服务器端已经准备好了,可以进行下一步的通信。

  2. 确认客户端的接收能力: 第三次握手是客户端向服务器端发送确认信息,表示自己也已经准备好接受连接。这个确认信息主要是为了确保客户端的接收能力。因为在第二次握手后,服务器端已经知道客户端的发送能力,但客户端的接收能力还需要确认一下。如果服务器端收到了客户端的确认信息,就知道客户端的接收能力是正常的,可以进行双向通信了。

综上所述,第三次握手是为了确保双方都已经准备好了进行通信,并且确认客户端的接收能力,以保证通信的可靠性和正确性。

断开连接,为什么要进行第四次挥手?

TCP四次挥手是关闭TCP连接时的一种协议,确保通信双方的正确关闭连接。为什么要进行第四次挥手呢?让我解释一下:

  1. 客户端发起关闭请求: 第一次挥手是客户端向服务器端发送关闭连接的请求,表示客户端不再发送数据,希望关闭连接。

  2. 服务器端确认关闭请求: 第二次挥手是服务器端收到客户端的关闭请求后,向客户端发送确认信息,表示已经收到了关闭请求,并且准备关闭连接。

  3. 服务器端发送数据完成: 第三次挥手是服务器端关闭连接前,确保发送完所有数据。在这个阶段,服务器端可能还有一些数据需要发送给客户端,为了确保数据的完整性,服务器端会先发送完所有数据,然后再向客户端发送关闭连接的请求。

  4. 客户端确认关闭连接: 第四次挥手是客户端收到服务器端的关闭请求后,向服务器端发送确认信息,表示已经收到了关闭请求,并且准备关闭连接。这时候,客户端和服务器端都知道对方已经准备好了,可以安全地关闭连接。

综上所述,第四次挥手是为了确保双方都已经准备好了关闭连接,并且确认数据的完整性,以保证通信的可靠性和正确性。

第三次握手第四次挥手总结

无论是建立连接还是断开连接,第一次握手和挥手是发出自己的请求,或是建立连接请求,或是断开连接请求。

第二次握手和第三次挥手代表服务端准备好了(第二次挥手代表服务端开始准备断开连接)

第三次握手和第四次挥手代表客户端准备好了

无论是建立连接还是断开连接都需要双方都准备好,因此需要第三次握手和第四次挥手

第四次挥手后A为什么要等待2MSL呢?

1,确保第四次挥手成功(也就是确保B能收到A发送的确认信息)

因为有可能这个确认信息会丢失,而B发送的FIN信息需要一个确认,若未收到确认,B便会超时重传FIN信息,若此时A已经关闭,则无法B,B就不能关闭了,因此A需要等待一会,确保不再有没有超时重传的FIN信息了,也就是确保B已经收到A的确认并且关闭了。

2,2MSl之后,所有有这个连接产生的报文段都将在网络中消失,使得新连接中不会出现旧连接中的任何报文段。这一点也与1符合,若有FIN的重传消息,必定在2MSL之内到达A,而若在2MSL内未收到FIN的重传,说明没有B端没有发送FIN的重传,A就可以确保B收到了第四次挥手的确认信息

什么是TCP粘包以及应对措施

1.Q:什么是TCP粘包问题?

TCP粘包就是指发送方发送的若干包数据到达接收方时粘成了一包,从接收缓冲区来看,后一包数据的头紧接着前一包数据的尾,出现粘包的原因是多方面的,可能是来自发送方,也可能是来自接收方。

2.Q:造成TCP粘包的原因

(1)发送方原因

TCP默认使用Nagle算法(主要作用:减少网络中报文段的数量),而Nagle算法主要做两件事:

只有上一个分组得到确认,才会发送下一个分组
收集多个小分组,在一个确认到来时一起发送
Nagle算法造成了发送方可能会出现粘包问题

(2)接收方原因

TCP接收到数据包时,并不会马上交到应用层进行处理,或者说应用层并不会立即处理。实际上,TCP将接收到的数据包保存在接收缓存里,然后应用程序主动从缓存读取收到的分组。这样一来,如果TCP接收数据包到缓存的速度大于应用程序从缓存中读取数据包的速度,多个包就会被缓存,应用程序就有可能读取到多个首尾相接粘到一起的包。

3.Q:什么时候需要处理粘包现象?
  1. 如果发送方发送的多组数据本来就是同一块数据的不同部分,比如说一个文件被分成多个部分发送,这时当然不需要处理粘包现象
  2. 如果多个分组毫不相干,甚至是并列关系,那么这个时候就一定要处理粘包现象了
4.Q:如何处理粘包现象?

(1)发送方

对于发送方造成的粘包问题,可以通过关闭Nagle算法来解决,使用TCP_NODELAY选项来关闭算法。

(2)接收方

接收方没有办法来处理粘包现象,只能将问题交给应用层来处理。

应用层的解决办法简单可行,不仅能解决接收方的粘包问题,还可以解决发送方的粘包问题。

解决办法:

  • 格式化数据:每条数据有固定的格式(开始符,结束符),这种方法简单易行,但是选择开始符和结束符时一定要确保每条数据的内部不包含开始符和结束符。
  • 添加包头: 我们通常使用添加包头的方式轻松地解决掉这个问题。关于数据包的包头大小可以根据自己的实际需求进行设定,这里没有啥特殊需求,因此规定包头的固定大小为4个字节,用于存储当前数据块的总字节数。:发送每条数据时,将数据的长度一并发送,例如规定数据的前4位是数据的长度,应用层在处理时可以根据长度来判断每个分组的开始和结束位置。
  • 使用标准应用层协议

————————————————
原文链接:https://blog.csdn.net/weixin_41047704/article/details/85340311

  • 33
    点赞
  • 30
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值