我对应用程序中增加TCP窗口大小有一些疑问。在我的C ++软件应用程序中,我们使用TCP / IP阻塞套接字从客户端向服务器发送大小约为1k的数据包。最近我遇到了这个概念TCP窗口大小。因此,我尝试使用setsockopt()
和SO_SNDBUF
SO_RCVBUF
将值增加到64K。增加此值后,我在WAN连接的性能方面有所改进,但在LAN连接方面却没有。
根据我对TCP窗口大小的理解,
客户端将数据包发送到服务器。在达到此TCP窗口大小时,它将等待确保从服务器接收到窗口大小中第一个数据包的ACK。在WAN连接的情况下,由于RTT的延迟大约100ms,ACK从服务器延迟到客户端。因此,在这种情况下,增加TCP窗口大小可以补偿ACK等待时间,从而提高性能。
我想了解我的应用程序中性能如何提高。
在我的应用程序中,即使在套接字级别使用setsockopt
增加TCP窗口大小(发送和接收缓冲区),我们仍然保持相同的1k数据包大小(即我们从客户端发送到服务器的字节数)在一个插座发送)。我们还禁用了Nagle算法(内置选项将小数据包合并到一个大数据包中,从而避免频繁的套接字调用)。
我的怀疑如下:
由于我正在使用阻塞套接字,因此对于每个1k的数据包发送,如果ACK不是来自服务器,它应该阻止。那么仅在WAN连接中改进TCP窗口大小后,性能如何提高?如果我误解了TCP窗口大小的概念,请纠正我。
为了发送64K数据,我相信我仍然需要调用套接字发送功能64次(因为我通过阻塞套接字发送每次发送1k),即使我将TCP窗口大小增加到64K。请确认一下。
使用RFC 1323算法启用Windows缩放时,TCP窗口大小的最大限制是什么?
我的英语不太好。如果您无法理解上述任何内容,请告知我们。
答案 0 :(得分:33)
首先,从您的问题可以看出一个很大的误解:TCP窗口大小由SO_SNDBUF
和SO_RCVBUF
控制。事实并非如此。
简而言之,TCP窗口大小决定了在收到尚未确认的最早数据包的确认之前,您的网络堆栈愿意将多少后续数据(数据包)放在线路上。
TCP堆栈必须存在并考虑到这样一个事实:一旦确定数据包在传输过程中丢失或损坏,从那个发送的每个数据包必须重新发送因为分组只能由接收者按顺序确认。因此,允许同时存在太多未确认的数据包消耗连接的带宽推测:无法保证所使用的带宽实际上会产生任何有用的信息。
另一方面,不允许同时发送多个未确认的数据包会简单地消除具有高bandwidth-delay product的连接的带宽。因此,TCP堆栈必须在使用带宽没有任何好处和不足够积极地驱动管道(从而允许其部分容量未使用)之间取得平衡。
TCP窗口大小决定了达到此平衡的位置。
SO_SNDBUF
和SO_RCVBUF
做了什么?它们控制网络堆栈为服务套接字而保留的缓冲区空间量。这些缓冲区用于累积堆栈尚未放在线路上的传出数据以及从线路接收但尚未分别由应用程序读取的数据。
如果其中一个缓冲区已满,则在释放一些空间之前,您将无法发送或接收更多数据。请注意,这些缓冲区仅影响网络堆栈处理网络接口“近”侧数据的方式(在发送之前或到达之后),而TCP窗口会影响堆栈管理“远”数据的方式。接口的一侧(即在电线上)。
没有。如果是这种情况,则会对发送的每个数据包产生往返延迟,这将完全破坏高延迟连接的带宽。
是的,但这与TCP窗口大小或分配给该套接字的缓冲区大小无关。
根据我能找到的所有来源(example),缩放允许窗口达到1GB的最大大小。
答案 1 :(得分:1)
- 由于我正在使用阻塞套接字,因此对于每个1k的数据包发送,如果ACK不是来自服务器,它应该阻止。
醇>
错误。在TCP中发送是异步的。 send()只是将数据传输到套接字发送缓冲区并返回。它仅在套接字发送缓冲区已满时阻塞。
那么仅在WAN连接中改进TCP窗口大小后性能如何提高?
因为你在阻止它之前就错了。
- 对于发送64K数据,我相信我仍然需要调用套接字发送功能64次
醇>
为什么呢?您可以使用64k数据缓冲区调用一次。
(因为我通过阻塞套接字每次发送1k)
为什么呢?或者这是在(1)下重复你的误解吗?
即使我将TCP窗口大小增加到64K。请确认一下。
没有。您可以一次发送所有内容。不需要循环。
使用RFC 1323算法启用Windows缩放时,TCP窗口大小的最大限制是多少?
比你需要的要大得多。