增加TCP窗口大小

Increasing TCP Window Size

本文关键字:窗口大小 TCP 增加      更新时间:2023-10-16

我对在应用程序中增加TCP窗口大小有一些疑问。在我的c++软件应用程序中,我们使用TCP/IP阻塞套接字将大小约为1k的数据包从客户端发送到服务器。最近我遇到了TCP窗口大小这个概念。因此,我尝试将SO_SNDBUFSO_RCVBUF使用setsockopt()的值增加到64K。在增加这个值之后,我在WAN连接中得到了一些性能改进,但在LAN连接中没有。

根据我对TCP窗口大小的理解,

客户端将向服务器发送数据包。在达到这个TCP窗口大小后,它将等待确保从服务器接收到窗口大小中的第一个数据包的ACK。在WAN连接的情况下,由于RTT中的延迟大约为100ms,因此从服务器到客户端的ACK延迟。因此,在这种情况下,增加TCP窗口大小补偿ACK等待时间,从而提高性能。

我想了解我的应用程序的性能是如何提高的。

在我的应用程序中,即使TCP窗口大小(发送和接收缓冲区)在套接字级别使用setsockopt增加,我们仍然保持相同的1k数据包大小(即我们在单个套接字发送中从客户端发送到服务器的字节)。我们还禁用了Nagle算法(将小数据包合并为大数据包的内置选项,从而避免频繁的套接字调用)。

我的疑问如下:

  1. 由于我使用阻塞套接字,对于每个1k的数据包发送,如果ACK没有来自服务器,它应该阻塞。那么仅在广域网连接中提高TCP窗口大小后,性能如何提高?如果我误解了TCP窗口大小的概念,请纠正我

  2. 对于发送64K的数据,我相信我仍然需要调用套接字发送函数64次(因为我通过阻塞套接字发送1k),即使我将TCP窗口大小增加到64K。

  3. 使用RFC 1323算法使能窗口缩放时TCP窗口大小的最大限制是多少

我的英语不太好。如果你有任何不明白的地方,请告诉我。

首先,从你的问题中可以明显看出一个很大的误解:TCP窗口大小是由SO_SNDBUFSO_RCVBUF控制的。这不是真的。

TCP窗口大小是多少?

简而言之,TCP窗口大小决定了在接收到尚未被确认的最早的数据包之前,您的网络堆栈愿意将多少后续数据(数据包)放在线上。

TCP栈必须接受并解释这样一个事实:一旦一个包在传输过程中被确定丢失或损坏,从那个开始发送的每个包都必须重新发送,因为包只能按顺序被接收方确认。因此,允许太多未确认的数据包同时存在,会推测地消耗连接的带宽:无法保证所使用的带宽实际上会产生任何有用的东西。

另一方面,不允许同时接收多个未确认的数据包只会消耗具有高带宽延迟产品的连接的带宽。因此,TCP栈必须在毫无益处地使用带宽和不积极地驱动管道(从而允许其部分容量未被使用)之间取得平衡。

TCP窗口大小决定了这个平衡点在哪里。

SO_SNDBUFSO_RCVBUF做什么?

它们控制网络堆栈为服务您的套接字而保留的缓冲区空间的数量。这些缓冲区分别用于积累堆栈尚未能够放到网络上的传出数据和从网络接收但尚未被应用程序读取的数据。

如果其中一个缓冲区已满,在释放一些空间之前,您将无法发送或接收更多的数据。请注意,这些缓冲区只影响网络堆栈如何处理网络接口"近"端的数据(在它们被发送之前或在它们到达之后),而TCP窗口影响堆栈如何管理接口"远"端的数据(即在线路上)。

回答您的问题

  1. 。如果是这种情况,那么您将导致每个发送的数据包的往返延迟,这将完全破坏高延迟连接的带宽。

  2. 是的,但这与TCP窗口大小或分配给该套接字的缓冲区大小无关。

  3. 根据我所能找到的所有来源(示例),缩放允许窗口达到1GB的最大大小。

  1. 由于我使用阻塞套接字,对于每个数据包发送1k,它应该阻塞如果ACK没有来自服务器。

是错误的。TCP的发送是异步的。Send()只是将数据传输到套接字发送缓冲区并返回。它只在套接字发送缓冲区满时阻塞。

那么仅在广域网连接中提高TCP窗口大小后,性能如何提高?

因为你错了,它阻塞直到它得到一个ACK。

  1. 发送64K的数据,我认为我仍然需要调用socket发送函数64次

为什么?你可以用64k的数据缓冲区调用它一次。

(因为我通过阻塞套接字每次发送1k)

为什么?或者这是你在第(1)项下的误解的重复?

,即使我把TCP窗口大小增加到64K。请确认。

。你可以一次全部发过去。不需要循环

使用RFC 1323算法启用窗口缩放时TCP窗口大小的最大限制是什么?