网络原理 ----TCP

一,TCP协议

在这张图中,前六行是报头,最后一行是载荷(真实的TCP协议是一行的,在这张图中是每四个字节换一行)

TCP全称为"传输控制协议(TransmissionControlProtocol").⼈如其名,要对数据的传输进行⼀个详细 的控制

  • 源/目的端口 :表示数据从哪个进程来,到哪个进程去
  • 4位首部长度:描述一个TCP报头的长度(TCP报头的长度可变,导致需要有一个属性描述到底是多长),4bit的范围为0~15,此处的单位是4字节,所以TCP报头的最大长度为60字节,最小长度为20字节(一行四个字节,"选项"之前一共五行)
  • 选项:(optional 可选的)选项中有很多个属性,可以选择一个,也可以选择多个,还可以一个都不选
  • 保留(6位):现在不用,但是留给未来做扩展,吸取了udp的教训
  • 4位TCP报头长度:表示该TCP头部有多少个32位bit(有多少个4字节),所以TCP头部最大长度是15* 4 = 60
  • 6个标志位: URG:紧急指针是否有效
  • ACK:确认号是否有效
  • PSH:提示接收端应用程序立刻从TCP缓冲区把数据读走
  • RST:对⽅要求重新建⽴连接;我们把携带RST标识的称为复位报文段
  • SYN:请求建⽴连接;我们把携带SYN标识的称为同步报⽂段
  • FIN:通知对⽅,本端要关闭了,我们称携带FIN标识的为结束报⽂段

二,TCP的核心机制

2.1 可靠传输

一个数据发出去,到对方收到,中间经过很多的路由器/交换机,这些路由器/交换机,相当于"路口",每个路由器/交换机,转发能力有上限,如果某个时刻的数据传输量暴增,可能超出某个设备的转发能力上限

但是在网络世界中,数据是有时效性的,数据"堵车"了,等到达最终目标就无意义了,不如直接丢包(丢包通常是路由器/交换器的主动行为)

所以丢包是客观存在的,并且无法预知什么时候产生丢包

"可靠传输"就是对抗丢包的

1,感知到丢包

2,丢包后有补救措施

2.2 如何实现可靠传输

核心机制1:确认应答

确认应答是实现可靠传输的核心机制

能够感知到对方是否收到,对方收到之后,回复一个"收到"

确认应答是通过特殊的数据包来实现的,在6位保留位中,

其中的第二个ACK,这一位如果为1就表示应答数据报,ACK即acknowledge应答

可能会有"后发先至"的随机事件:发的数据包,就相当于一辆一辆的车,经过的每个路由器交换机就是路口,每个数据包在经由路由器转发的时候,走的路径可能不同(后面的车,可能会抄近道什么的)

所以,应答是需要的,但是需要考虑应答的顺序

可以给数据编号,此时应答数据可以根据编号,完成应答

TCP实际上是根据每个字节进行的编号,采取了连续递增的整数来对数据进行编号(所以只需要知道数据中第一个字节的编号,后面每个字节的编号就都知道了)

编号是给载荷部分编号,报头部分不需要编号

报头中32位序号,此处保存的就是当前数据包载荷中第一个字节的编号

应答报文,要根据序号来进行应答

例如:发送方发送1~44,接收方收到了这些数据,返回ack,告诉发送方,收到了哪些数据

应答报文中的确认序号,填写的值,是收到的数据最后一个字节的序号 + 1,而不是第一个字节的序号

可以理解成:1,接收方在告诉发送方,哪个序号前面的数据,全都收到了

2,接收方也是在向发送方索要下一个数据,从哪里开始

发送1-1000的时候,TCP是一个普通的TCP数据报,此时序号这里填写成1,ACK标志位为0

返回应答报文1001的时候,TCP是一个应答数据报,此时序号这里是独立编号(根据方向来编号的),确认序号这里填写的是1001,ACK标志位为1,同时ACK数据报的载荷是空的

核心机制2:超时重传

超时重传是针对确认应答进行的重要补充,也是实现可靠传输的核心机制

丢包是客观存在的,随机出现

如果丢包了,就把丢的数据重发一遍(重发数据是可以对抗丢包的)

Q:如何判定是否丢包?

A:根据ack的等待时间来判定

  • 主机A发送数据给B之后,可能因为网络拥堵等原因,数据无法到达主机B
  • 如果主机A在⼀个特定时间间隔内没有收到B发来的确认应答,就会进行重发

但是,主机A未收到B发来的确认应答,也可能是因为ACK丢失了

因此主机B会收到很多重复数据.那么TCP协议需要能够识别出那些包是重复的包,并且把重复的丢弃掉

这时候我们可以利用前面提到的序列号,就可以很容易做到去重的效果,保证同一份序号的数据,应用程序这里只能read到一次

在接收方中,操作系统内核中,有一个接受缓冲区(内存),每个socket都有自己独立的接收缓冲区,每次收到新的数据,操作系统判定当前这个序号是否已经在缓冲区中存在了,如果存在了,就直接把这个数据丢弃了,不存在,才放到接收缓冲区中,应用程序读取数据,从接收缓冲区来读取

数据在接收缓冲区中,作用有:

1,去重

2,重新排序(保证应用程序读到的数据就是发送的顺序,解决了后发先至的问题)

Q:超时的时间如何确定?

A:最理想的情况下,找到⼀个最小的时间,保证"确认应答⼀定能在这个时间内返回".

• 但是这个时间的长短,随着网络环境的不同,是有差异的.

• 如果超时时间设的太长,会影响整体的重传效率;

• 如果超时时间设的太短,有可能会频繁发送重复的包

TCP为了保证无论在任何环境下都能⽐较⾼性能的通信,因此会动态计算这个最⼤超时时间

• Linux中(BSDUnix和Windows也是如此),超时以500ms为⼀个单位进行控制,每次判定超时重发的 超时时间都是500ms的整数倍.

• 如果重发⼀次之后,仍然得不到应答,等待2*500ms后再进行重传.

• 如果仍然得不到应答,等待4*500ms进行重传.依次类推,以指数形式递增.

• 累计到⼀定的重传次数,TCP认为网络或者对端主机出现异常,强制关闭连接.

注意,重传的时间不是无限长的,重传的次数也不是无限的,有一定的阈值,达到一定的程度,就会视为"网络出现严重故障",放弃通信了(释放连接)

核心机制3:连接管理

连接管理对于可靠传输起辅助作用

在正常情况下,TCP要经过三次握手建立连接,四次挥手断开连接

建立连接

建立连接的工作过程,称为"三次握手"

握手即计算机中常见的专业术语,握手就是打招呼,其本身这个动作并不传递实质性的业务数据(应用层数据包),仅仅是打招呼(握手过程中,传递的是"只有报头,没有载荷"的TCP数据报)

建立连接是通信双方的事情,一个巴掌拍不响

客户端需要告诉服务器:"我要和你建立连接"(即我要保存你的信息)

服务器也要告诉客户端:"我也要和你建立连接"(即我也要保存你的信息)

通信双方把对方的信息都保存了,连接才算完成

如图,从上到下,时间在推移,谁发起第一次请求,谁就是客户端(即谁主动谁是客户端)

在这个请求中,报头里,包含一个SYN标记(和 synchronized同步 完全不同)

多线程的"加锁"的"同步"本质上是"互斥"

TCP这里的同步,其实是一种"通知",表示接下来要进行通信了

此处这个syn数据报,也称为"同步报文段"

图中有四次网络通信,但是建立连接却称为三次握手,是因为中间两次的网络通信是可以合并的(中间两次的数据传输,时机是完全相同的:1,收到syn之后,第一时间来返回内容。2,把两个数据合并成一个,提高传输效率(合并成一次只需要封装分用一次,分两次发送,需要封装分用两次))

三次握手的意义

1)投石问路,初步的验证了++网络通信路径是畅通的++(是后续进行可靠传输的前提条件)

2)验证通信双方的发送能力和接收能力是否正常

3)三次握手过程中,还可以完成一些参数协商

三次握手中,协商的一个重要的参数,序号从哪里开始

TCP通信时,序号大概率不是从1开始的

三次握手的时候,客户端和服务器,各自生成一个自己的初始序号,通过三次握手告诉对方,对方就知道接下来咱们的通信,你的数据会从哪个序号开始

三次握手是否可以改成四次?两次?

1)可以改成四次,但是没有必要

中间的两次通信,最好还是合并在一起,不要拆开,拆开效率会比较低

2)不可以改成两次

TCP的状态转换
CLOSE

这是一个虚拟的状态,表示TCP连接释放了(不存在)

LISTEN

listen:服务器进入的专属状态,表示服务器已经准备就绪,随时可以用客户端来建立连接

eg:手机开机,信号良好,随时可以有人打电话给你

SYN_SENT

客户端发送出第一个syn处于的状态

SYN_RCVD

服务器收到第一个syn处于的状态

上面两个状态SYN_SENT和SYN_RCVD,很难直接看到,存在的时间非常短,但是如果通信存在问题,此时就可以看到这样的状态

ESTABLISHED

established:表示连接完成

表示接下来可以进行数据通信了

断开连接

断开连接需要四次++挥手++(都表示一个不携带载荷,没有业务意义,表示特定功能的tcp数据报)

在三次握手中,一定是客户端开始第一个操作,但是在四次挥手中,客户端和服务器都有可能是主动发起的一方

FIN:结束报文段

Q:中间的两次能否合并变成三次挥手?

不一定,有的时候可以(触发特殊机制),有时不可以(标准情况下)

不能合并的关键,在于服务器方返回ack和发送fin的时机是不同的

ack是在收到fin之后,由操作系统内核控制,自动的,立刻的返回

fin 则需要应用程序,执行到close方法(进程退出),才会触发

所以是有时间差的

TIME_WAIT

谁主动断开连接,谁就会进入这个状态

等待一定时间之后,再释放连接

进入这个状态之后,正常情况下不会收到,也不会发送任何数据了

静静的等待一段时间,连接就自然释放了

1)Q:如果没有time_wait直接释放会怎样?

最后一个ack可能会丢包!

如果是前面的数据包丢包,直接触发超时重传就可以了,因为此时通信双方的连接都正常工作,重传都能处理

但是最后一个ack丢包,此时对方就会重传fin,此时客户端这边已经释放了连接的话,就没有人响应fin 的重传数据,没有人能返回ack了

2)为什么是TIME_WAIT的时间是2MSL?

操作系统中有一个参数,MSL,表示网络通信中数据从一端到另一端传输经历的最大时间

• MSL是TCP报⽂的最⼤⽣存时间,因此TIME_WAIT持续存在2MSL的话

• 就能保证在两个传输⽅向上的尚未被接收或迟到的报⽂段都已经消失(否则服务器⽴刻重启,可能会 收到来⾃上⼀个进程的迟到的数据,但是这种数据很可能是错误的);

• 同时也是在理论上保证最后⼀个报⽂可靠到达(假设最后⼀个ACK丢失,那么服务器会再重发⼀个 FIN. 这时虽然客⼾端的进程不在了,但是TCP连接还在,仍然可以重发LAST_ACK)

CLOSE_WAIT

等待执行close方法

⼀般⽽⾔,对于服务器上出现⼤量的CLOSE_WAIT状态,原因就是服务器没有正确的关闭socket,导致 四次挥⼿没有正确完成.这是⼀个BUG.只需要加上对应的close即可解决问题

核心机制4:滑动窗口

这个窗口就是个比喻,窗口内部可以过去,但是窗口外部就不可以过去

刚才我们讨论了确认应答策略,对每⼀个发送的数据段,都要给⼀个ACK确认应答.收到ACK后再发送下 ⼀个数据段.这样做有⼀个⽐较⼤的缺点,就是性能较差.尤其是数据往返的时间较⻓的时候.

既然这样⼀发⼀收的⽅式性能较低,那么我们⼀次发送多条数据,就可以⼤⼤的提⾼性能(其实是将多个 段的等待时间重叠在⼀起了).

注意:批量发送数据,也不能无限大的批量发送,批量发送的数据越多,效率确实越高。但是,批量发送的数据太多了,对于可靠性也是有影响的

所以需要对批量发送的"度"进行限制(定量的衡量)

这个概念称为窗口,能够不阻塞的,发送数据的最大的量,就称为"窗口大小"(窗口大小指的是无需等待确认应答而可以继续发送数据的最⼤值.上图的窗口大小就是4000个字节 (四个段))

如图:1,发送前四个段的时候,不需要等待任何ACK,直接发送

2,收到第⼀个ACK后,滑动窗⼝向后移动,继续发送第五个段的数据;依次类推

3,操作系统内核为了维护这个滑动窗⼝,需要开辟发送缓冲区来记录当前还有哪些数据没有应答;只有确认应答过的数据,才能从缓冲区删掉

4,窗⼝越⼤,则⽹络的吞吐率就越⾼

Q:当收到1001这个ack的时候是继续等,等到4001再次批量发送四组数据还是收到1001之后,立刻发送一组数据?

A:收到1001之后,立刻发送一组数据


滑动传输是TCP中用来提升传输效率的机制,但是TCP再怎么提高,也不可能比UDP快

Q:如果出现了丢包,如何进行重传?这里分两种情况讨论

1)情况一:数据包已到达,ack被丢了

这种情况下的丢包不用管,因为"确认序号"填写的是收到数据最后一个字节序号+1,意思就是这个序号之前的数据就全部收到了

比如"下一个是5001"这个ack的含义就是5001之前的数据都收到了,包含了1-1000,1001-2000等等

2)情况二:数据包丢了

数据丢了则需要重传

如图:当1001-2000丢了之后,接下来2001-3000这个数据到达对方,对方返回的ack是1001(不是3001)

当某⼀段报⽂段丢失之后,发送端会⼀直收到1001这样的ACK,就像是在提醒发送端"我想要的是 1001" ⼀样

如果发送端主机连续三次收到了同样⼀个"1001"这样的应答,就会将对应的数据1001-2000重新发送

这个时候接收端收到了1001之后,再次返回的ACK就是7001了(因为2001-7000)接收端其实之前就已经收到了,被放到了接收端操作系统内核的接收缓冲区中

这种机制被称为"高速重发控制"(也叫"快重传")


确认应答和滑动窗口这两种机制是共同配合的,适用于不同的场景

1,如果传输的数据频次低(两次传输数据的间隔比较大)就使用确认应答---超时重传

2,如果传输的数据频次高(连续不断的write数据)就使用滑动窗口---快速重传

核心机制5:流量控制

接收端处理数据的速度是有限的.如果发送端发的太快,导致接收端的缓冲区被打满,这个时候如果发送端继续发送,就会造成丢包,继⽽引起丢包重传等等⼀系列连锁反应

因此TCP⽀持根据接收端的处理能⼒,来决定发送端的发送速度.这个机制就叫做流量控制(Flow Control)

• 接收端将自己可以接收的缓冲区大小放入TCP首部中的"窗口大小"字段,通过ACK端通知发送端;

• 窗口大小字段越大,说明网络的吞吐量越高;

• 接收端⼀旦发现自己的缓冲区快满了,就会将窗口大小设置成⼀个更小的值通知给发送端;

• 发送端接受到这个窗口之后,就会减慢自己的发送速度;

• 如果接收端缓冲区满了,就会将窗⼝置为0;这时发送⽅不再发送数据,但是需要定期发送⼀个窗⼝探 测数据段,使接收端把窗⼝⼤⼩告诉发送端

接收方每次收到数据之后,都会计算出剩余缓冲区的大小,把这个值通过ack返回给发送方,发送方就可以参考这个数字,设置下一轮滑动窗口的大小

Q:接收端如何把窗口大小告诉发送端呢?

A:TCP⾸部中,有⼀个16位窗⼝字段,就是存放了窗⼝⼤⼩信息(仅仅是在ack数据报中才有效)

注意:这里指定的数字是16bit,但是并不意味着最大就是64KB,因为在"选项"中还有一个"窗口扩展因子",而实际反馈的数值 = 16位窗口大小 << 窗口扩展因子,所以发送方会以收到的"16位窗口大小"作为下一轮次,滑动窗口的窗口大小

1,使用接收缓冲区剩余空间大小,定量的衡量,接收方的处理能力

2,通过ack的窗口大小,通知发送方,窗口大小是多少

3,发送根据收到的ack的窗口大小,调整滑动窗口的大小

4,如果窗口的大小为0,此时发送方暂停发送业务数据,任然会周期性的发送窗口探测报文

上述都是TCP内部实现的

核心机制6:拥塞控制

虽然TCP有了滑动窗⼝这个⼤杀器,能够⾼效可靠的发送⼤量的数据.但是如果在刚开始阶段就发送⼤量 的数据,仍然可能引发问题.

因为⽹络上有很多的计算机,可能当前的⽹络状态就已经⽐较拥堵.在不清楚当前⽹络状态下,贸然发送 ⼤量的数据,是很有可能引起雪上加霜的.

TCP引⼊慢启动机制,先发少量的数据,探探路,摸清当前的⽹络拥堵状态,再决定按照多⼤的速度传输 数据

拥塞控制也是制约流量控制的,发送效率

流量控制是根据接收方的处理能力进行制约的

拥塞控制是根据中间的通信链路来进行制约的

拥塞控制的思路:

首先按照比较慢的速度,发送数据

如果没有丢包(链路畅通),放大窗口,加快速度

如果出现丢包(链路堵塞),减小窗口,放慢速度

通过这样的方式,"尝试"出合适的窗口大小

如图:纵轴的拥塞窗口直接决定了发送方发送的窗口大小,纵轴的单位可以理解为"多少份",一份可以是若干个字节

初始情况下,按照比较小的窗口来传输数据(传输速度比较慢,称为慢启动)

没有出现丢包,窗口大小会进一步变大,按照指数的方式增长

并且给窗口大小引入阈值,当窗口大小超过阈值的时候不再指数增长,而是线性增长(为了避免某一个轮次,窗口突然变得很大,导致出现严重丢包)

一旦出现丢包,就视为出现了拥堵了,当前就得减小窗口大小了

1)旧版本:直接回到最初的慢开始状态,非常小的窗口进行

指数增长,线性增长

2)新版本:回到新的阈值位置(丢包位置的窗口大小/2)从这个位置继续进行线性增长

核心机制7:延迟应答

延迟应答用于提高传输效率,即接收方收到数据的时候,不会立即返回ack,而是稍等一会。在这稍等的一会中,接收方的应用程序就可以多消费一部分数据了,从而反馈一个更大的窗口

如果接收数据的主机⽴刻返回ACK应答,这时候返回的窗⼝可能⽐较⼩

• 假设接收端缓冲区为1M.⼀次收到了500K的数据;如果⽴刻应答,返回的窗⼝就是500K;

• 但实际上可能处理端处理的速度很快,10ms之内就把500K数据从缓冲区消费掉了;

• 在这种情况下,接收端处理还远没有达到⾃⼰的极限,即使窗⼝再放⼤⼀些,也能处理过来;

• 如果接收端稍微等⼀会再应答,⽐如等待200ms再应答,那么这个时候返回的窗⼝⼤⼩就是1M;

⼀定要记得,窗⼝越⼤,⽹络吞吐量就越⼤,传输效率就越⾼.我们的⽬标是在保证⽹络不拥塞的情况下 尽量提⾼传输效率

Q:所有的包都可以延迟应答么?

A:并不是

数量限制:每隔N个包就应答⼀次

时间限制:超过最⼤延迟时间就应答⼀次

具体的数量和超时时间,依操作系统不同也有差异;⼀般N取2,超时时间取200ms

在延时时间里,可能是水位降低了,也可能是水位升高了,所以说延时应答也不能确保返回的窗口100%更大,甚至可能变小(根据经验规律,大部分的情况下,还是会变大的,因为一旦水位线提升,此时发送速度就会降低(流量控制))

Q:延迟应答要延时多久?

A:不能延迟太久,不然会触发超时重传

另一方面,也会按照ack的个数来进行延时应答

批量返回ack的时候,每隔N个数据包,返回一个ack

核心机制8:捎带应答

捎带应答是在延时应答的基础上,进一步提高效率

在延迟应答的基础上,我们发现,很多情况下,客⼾端服务器在应⽤层也是"⼀发⼀收"的.意味着客⼾端 给服务器说了"Howareyou",服务器也会给客⼾端回⼀个"Fine,thankyou"

那么这个时候ACK就可以搭顺⻛⻋,和服务器回应的"Fine,thankyou"⼀起回给客⼾端

如图,应用程序需要一定的计算和逻辑,生成响应,正常情况下,ack和响应是两个不同的时间,但是ack由延时应答,在等一会的过程中,正好ack就可以搭载响应的顺风车,返回的响应数据,既是响应数据,也是一个ack

核心机制9:面向字节流

创建⼀个TCP的socket,同时在内核中创建⼀个发送缓冲区和⼀个接收缓冲区

• 调⽤write时,数据会先写⼊发送缓冲区中;

• 如果发送的字节数太⻓,会被拆分成多个TCP的数据包发出;

• 如果发送的字节数太短,就会先在缓冲区⾥等待,等到缓冲区⻓度差不多了,或者其他合适的时机发 送出去;

• 接收数据的时候,数据也是从⽹卡驱动程序到达内核的接收缓冲区;

• 然后应⽤程序可以调⽤read从接收缓冲区拿数据;

• 另⼀⽅⾯,TCP的⼀个连接,既有发送缓冲区,也有接收缓冲区,那么对于这⼀个连接,既可以读数据, 也可以写数据.这个概念叫做全双⼯

由于缓冲区的存在,TCP程序的读和写不需要⼀⼀匹配,例如:

• 写100个字节数据时,可以调⽤⼀次write写100个字节,也可以调⽤100次write,每次写⼀个字节;

• 读100个字节数据时,也完全不需要考虑写的时候是怎么写的,既可以⼀次read100个字节,也可以⼀ 次read⼀个字节,重复100次;

粘包问题

• ⾸先要明确,粘包问题中的"包",是指的应⽤层的数据包.

• 在TCP的协议头中,没有如同UDP⼀样的"报⽂⻓度"这样的字段,但是有⼀个序号这样的字段.

• 站在传输层的⻆度,TCP是⼀个⼀个报⽂过来的.按照序号排好序放在缓冲区中.

• 站在应⽤层的⻆度,看到的只是⼀串连续的字节数据.

• 那么应⽤程序看到了这么⼀连串的字节数据,就不知道从哪个部分开始到哪个部分,是⼀个完整的应⽤层数据包

那么如何避免粘包问题呢?归根结底就是⼀句话,明确两个包之间的边界

• 对于定⻓的包,保证每次都按固定⼤⼩读取即可;例如上⾯的Request结构,是固定⼤⼩的,那么就从 缓冲区从头开始按sizeof(Request)依次读取即可;

• 对于变⻓的包,可以在包头的位置,约定⼀个包总⻓度的字段,从⽽就知道了包的结束位置;

• 对于变⻓的包,还可以在包和包之间使⽤明确的分隔符(应⽤层协议,是⾃⼰来定的,只要保证 分隔符不和正⽂冲突即可)

对于UDP协议来说,是否也存在"粘包问题"呢?

• 对于UDP,如果还没有上层交付数据,UDP的报⽂⻓度仍然在.同时,UDP是⼀个⼀个把数据交付给应 ⽤层.就有很明确的数据边界.

• 站在应⽤层的站在应⽤层的⻆度,使⽤UDP的时候,要么收到完整的UDP报⽂,要么不收.不会出 现"半个"的情况.

核心机制10:异常情况

进程崩溃

本质上和正常断开连接的过程是一样的

调用close方法触发 fin 和进程退出触发 fin 都是文件描述符表中的内容被释放了,无论是主动释放还是操作系统统一释放都是释放了

• 进程终⽌:进程终⽌会释放⽂件描述符,仍然可以发送FIN.和正常关闭没有什么区别.

主机关机

• 机器重启:和进程终⽌的情况相同.

主机断电/网线断开

1)接收方掉电

之前客户端发数据都是有ack的,突然没有ack,此时客户端会触发超时重传,最后单方面释放连接,会触发一个特殊的数据包,复位报文

2)发送方断电

客户端断电,此时发送数据突然就没了。此时接收方会等,等发送方发送数据,如果一定时间没有收到数据的时候,就会触发"心跳包",探测对方是否在正常工作

1,没有心跳则挂了 2,心跳是周期性的

给对方发送不携带载荷的数据,等待对方的ack,如果对方有ack回来,说明对方的工作状态是正常的,如果对方没有ack回来则说明出问题了,此时接收方就可以单方面释放连接了

• 机器掉电/⽹线断开:接收端认为连接还在,⼀旦接收端有写⼊操作,接收端发现连接已经不在了,就 会进⾏reset.即使没有写⼊操作,TCP⾃⼰也内置了⼀个保活定时器,会定期询问对⽅是否还在.如果 对⽅不在,也会把连接释放.

另外,应⽤层的某些协议,也有⼀些这样的检测机制.例如HTTP⻓连接中,也会定期检测对⽅的状态.例 如QQ,在QQ断线之后,也会定期尝试重新连接.

三,TCP/UDP对比

TCP是可靠连接,那么是不是TCP⼀定就优于UDP呢?

TCP和UDP之间的优点和缺点,不能简单, 绝对的进⾏⽐较

• TCP⽤于可靠传输的情况,应⽤于⽂件传输,重要状态更新等场景;

• UDP⽤于对⾼速传输和实时性要求较⾼的通信领域,例如,早期的QQ,视频传输等.另外UDP可以⽤于⼴播(TCP只能一对一); 归根结底,TCP和UDP都是程序员的⼯具,什么时机⽤,具体怎么⽤,还是要根据具体的需求场景去判定.

3.1⽤UDP实现可靠传输

参考TCP的可靠性机制,在应⽤层实现类似的逻辑;

例如: • 引⼊序列号,保证数据顺序;

• 引⼊确认应答,确保对端收到了数据;

• 引⼊超时重传,如果隔⼀段时间没有应答,就重发数据

相关推荐
Ruiery44 分钟前
Linux 6.6内核 PCIe 深度解析(九):复位机制 — 从 FLR 到 Secondary Bus Reset 的降级链
linux·运维·服务器
舞动青春881 小时前
家用局域网私有云备份网站搭建
网络
学烹饪的小胡桃1 小时前
WGCLOUD支持哪些告警方式
linux·运维·服务器·网络·安全
qq7590353661 小时前
2026 docker部署Hub 监控中心管理多台服务器硬盘和内存
运维·服务器
sbjdhjd1 小时前
PHP RCE 多层绕过实战:关键字过滤、空格替换与 php://filter 伪协议 | 02
网络·安全·web安全·网络安全·云计算·安全架构·rce
Jay Kay1 小时前
深入理解 RDMA 内存管理:海思 HNS RoCE 架构中的 HEM 表与 MTR 表有什么区别?
服务器·网络·架构
木心术11 小时前
卫星通信技术全景:从低轨星座组网、相控阵 EIRP 工程计算到 NTN 标准演进(2026 深度梳理)
网络
weixin_440730501 小时前
socket简单介绍-三次握手四次断开+一个例子
运维·服务器
你怎么知道我是队长1 小时前
计算机网络中的 DNS 与 DHCP 详解
网络·计算机网络