You need to enable JavaScript to run this app.
最新活动
大模型
产品
解决方案
定价
生态与合作
支持与服务
开发者
了解我们

TCP内部缓冲区填满时的行为及客户端快发场景下的缓冲区问题

Hey there, let's break down your TCP questions one by one:

1. 当TCP内部缓冲区填满时会发生什么?

TCP的内部缓冲区其实分两种:发送缓冲区(属于发送端)和接收缓冲区(属于接收端),两者满了之后的表现不太一样,咱们分别说:

  • 接收缓冲区填满时:
    接收端的TCP会在给发送端的ACK报文中把窗口大小设为0,相当于直白告诉发送端:“我这边没地方存数据了,先停一停”。发送端收到这个窗口为0的ACK后,会立刻暂停发送新数据,进入等待状态。
    等接收端处理完缓冲区里的数据、腾出空间后,会主动给发送端发一个窗口更新报文,把当前可用的窗口大小同步给对方,发送端收到后就会恢复数据发送。
    另外,如果发送端等了很久都没收到窗口更新,还会触发窗口探测报文,用来确认接收端是不是真的还没腾出空间,避免因为报文丢失导致的永久等待。

  • 发送缓冲区填满时:
    如果是阻塞套接字,调用send()的时候会直接阻塞,直到缓冲区里已有数据被发送出去、腾出空间,send()才会返回成功。
    如果是非阻塞套接字send()会立刻返回错误码EAGAIN(或EWOULDBLOCK),明确告诉你现在缓冲区满了,没法发送,得稍后再尝试。

2. 客户端发送速度远快于服务器处理速度时,内部网络缓冲区是否会被填满?

答案是肯定会,咱们结合你给的伪代码来捋清楚整个过程:

你看服务器的逻辑:每次recv(4096)把数据读到data里,接着就去执行cpu_intensive_task(parsed_data)——这个CPU密集任务会占用大量时间,在这段时间里,服务器完全没有调用recv()去读取TCP接收缓冲区里的新数据。

而客户端是一直在循环调用send(data)发送数据,速度还比服务器处理快得多:

  1. 一开始,服务器的TCP接收缓冲区会不断接收客户端发来的数据,很快就会被填满。
  2. 接收缓冲区满了之后,服务器的TCP就会给客户端发窗口为0的ACK,客户端的发送端收到后会暂停发送新数据。
  3. 但客户端还在继续调用send(),如果客户端用的是阻塞套接字,send()会直接卡住;如果是非阻塞套接字,send()会返回错误。同时客户端的发送缓冲区也会被“已发送但未收到ACK”的数据填满(因为服务器没处理完数据,没法发ACK确认)。

简单说,服务器因为CPU密集任务拖慢了数据读取的节奏,导致接收缓冲区被占满,进而连锁反应让客户端的发送缓冲区也跟着满起来。


内容的提问来源于stack exchange,提问作者TukeV

火山引擎 最新活动