TCP缓存区与窗口的关系

本文澄清了网络编程中常见的误解,详细解释了TCP缓存区与窗口的关系,包括发送缓存区、发送窗口、接收缓存区及接收窗口的概念及其相互作用。文章通过实例帮助读者理解这些概念。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

网上大多错误的理解

  1. 滑动窗口大小=接受缓存区大小
  2. 接收方通告窗口大小=发送方缓存区大小

注意:以上两个结论都是错误的

我们在学习网络编程时,通常会参考两本很经典的书《UNIX网络编程 卷1》和《TCP/IP 卷1》。然而,我在看与缓存区与窗口相关模块知识点时,通常会犯迷糊。感觉这两本书对其的描述很少,描述得有点模糊。

《TCP/IP详解 卷1》第1版的一句重要的描述,因为在小字处,很容易被忽略。

插口API允许进程设置发送和接收缓存的大小。接收缓存的大小是该连接上所能够通告的最大窗口大小。

说明接收缓存 >= 接收方通告窗口大小。
侧面说明发送缓存区、发送窗口、接收缓存区、接收窗口的大小是不同的

《UNIX网络编程 卷1》第3版只用了2.11一个小节描述TCP缓存区,重要信息是(图2-15):
应用进程缓存区(任意大小)
套接字发送缓存区(SO_SNDBUF)

知识点:应用进程缓存区和套接字发送缓存区是分开的两个东西。TCP发送方分为两个过程。
1. 应用进程write数据到套接字缓存区。
2. TCP套接字从套接字缓存区读取数据,发送出去。

TCP缓存区与窗口关系结论

  1. 发送窗口不是发送方通告的窗口,而是接收方通告的窗口。
  2. 接收方通告的窗口大小=发送方窗口大小。
  3. 接收方通告的窗口大小也=自己的窗口大小(即接收方窗口大小)
  4. 发送缓存>发送方窗口>已发送字节
  5. 接收缓存>接收窗口>接收未确认字节
  6. TCP通信过程中,发送缓存和接收缓存大小不变,发送窗口和接收窗口可能会改变。

预备知识:窗口位置变化

这里写图片描述

发送窗口后沿的变化情况2种可能:
1. 不动:没有收到确认ACK。
2. 前移:收到确认ACK。

发送窗口前沿的变化情况2种可能:
1. 不动:
* 没有收到新的确认,对方通知的窗口大小不变。
* 收到新的确认,但对方通知的窗口缩小。
2. 前移:普遍情况。
3. 后缩:对方通知窗口缩小。但是TCP不赞成这样子做。

TCP缓存区与窗口关系理解

理解发送方缓存区与发送窗口的关系

这里写图片描述
由图可知,发送缓存暂时存放:
1. 发送应用程序传给发送TCP准备发送的数据。
2. TCP已发送出但尚未收到确认的数据。

发送窗口只是发送缓存的一部分。已发送但未被确认数据大小<=发送窗口的大小。已被确认的数据会从发送缓存中删除。发送缓存和发送窗口后沿(这里的左边)是重合的,因为一被确认就会删除。删除后发送缓存和发送窗口的后沿同时向左移。发送应用程序必须控制写入缓存的速率,不能太快,否则发送缓存会没有存放数据的空间。

理解接收方缓存区和窗口关系

这里写图片描述
由图可知,接收缓存暂时存放:
1. 按序到达、但尚未被接收应用程序读取的数据。
2. 未按序到达的数据。

如果接收应用程序来不及读取收到的数据,接收缓存最终会被填满,使接收窗口减少到0.反之,如果接收应用程序能够及时从接收缓存中读取收到的数据,接收窗口可以增大,但最大不能超过接收缓存的大小。接收缓存和接收窗口的前沿(图的右)是重合的。因为等应用程序读取数据后,可能向前沿移动。如果接收窗口<通告时指定大小,则同时向前移。如果接收窗口不能扩大了,则不移动,接收缓存有空闲区域。记住数据只能填充接收窗口,并不是正个接收缓存。

几个模糊问题

  1. 接收方通告的窗口=发送窗口,那么接收窗口=发送窗口吗?
    在同一时刻,发送窗口与接收窗口的大小并不一定相同。这是因为通过网络传送窗口值需要经历一定的时间滞后。另外,发送方还可能根据网络当时的拥塞情况适当减少自己的发送窗口数值(即慢启动和拥塞避免)。

  2. 发送窗口包含着以发送未接收确认ACK的数据,那么接收窗口包含按序到达但未被应用程序读取的数据吗?
    接收窗口包含的是未按序到达的和按序到达,但是将在未来不久后发送确认ACK的数据(累积确认)。不包含按序到达的,已发送了确认的数据。

  3. 接收窗口为什么会缩小?
    接收缓存由按序到达数据、接收窗口数据和空白区域组成。如果接收窗口发送确认ACK,则按序到达数据会增加,假设填满了空白区域,但是应用程序还是来不及读取,接收窗口大小只能减小。减小原来还包括太多未按序到达的数据霸占。

  4. 再补充。。。

### TCP缓存区工作机制和技术详解 #### 一、TCP缓存区概述 TCP缓存区主要分为发送缓冲区(Send Buffer)和接收缓冲区(Receive Buffer)。这些缓冲区的作用是在数据传输过程中临时存储待发送的数据以及接收到但尚未被应用程序读取的数据。这种设计可以有效提升网络通信的性能并缓解瞬时流量高峰带来的压力。 #### 二、发送缓冲区工作原理 当应用层向TCP提交数据时,如果数据无法立即发送到网络上,则会暂时保存在发送缓冲区内等待合适的时机进行传输。一旦条件满足——比如有足够大的窗口尺寸或者达到了延迟时间阈值——就会触发实际的数据包发送操作[^3]。此外,在拥塞控制策略下,为了防止过度占用带宽资源而导致整个互联网系统的崩溃风险增加,还需要遵循一定的速率限制规则来进行逐步试探性的加速过程直至找到最佳平衡点为止[^1]。 ```python import socket # 创建socket对象 sock = socket.socket(socket.AF_INET, socket.SOCK_STREAM) # 设置发送缓冲区大小 send_buffer_size = sock.getsockopt(socket.SOL_SOCKET, socket.SO_SNDBUF) print(f"Default Send Buffer Size: {send_buffer_size} bytes") new_send_buffer_size = 65536 # 自定义设置为64KB sock.setsockopt(socket.SOL_SOCKET, socket.SO_SNDBUF, new_send_buffer_size) ``` #### 三、接收缓冲区功能描述 对于到达的目标主机上的某个特定端口而言,所有针对该目标地址及端口号组合而来的IP分组都将先进入对应的队列之中排队等候处理;随后再按照先后顺序逐一取出交给更高层次的应用程序去解析使用。在此期间如果有任何错误发生(例如校验失败),那么相应的帧会被丢弃并不计入统计总数之内[^2]。 ```python # 获取当前套接字的接收缓冲区大小 recv_buffer_size = sock.getsockopt(socket.SOL_SOCKET, socket.SO_RCVBUF) print(f"Default Receive Buffer Size: {recv_buffer_size} bytes") new_recv_buffer_size = 131072 # 自定义设置为128KB sock.setsockopt(socket.SOL_SOCKET, socket.SO_RCVBUF, new_recv_buffer_size) ``` #### 四、调整优化建议 合理配置这两个参数能够显著改善用户体验质量(QoS),特别是在高延迟低带宽环境下尤为明显; 同时也要注意避免盲目增大数值以免引发其他副作用如内存耗尽等问题出现. ---
评论 6
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值