我有一个奇怪的问题,即 select 在 Linux 中的套接字上花费了意外的时间。
- 服务器一直在接收数据,接收套接字缓冲区大小为65536。
- 客户端一直在发送数据,发送套接字缓冲区大小为4096。
一般来说,数据传输速度非常快。但是:客户端中的一个 select 来测试写入是否不会阻塞需要很长时间(之前不调用 select 发送数据:0.5s,在实际发送数据之前调用 select 发送相同的数据:5s)。该问题特定于缓冲区大小。如果我将客户端中的发送缓冲区增加到比方说 4*4096,问题就会消失。
现在我想知道为什么选择特定缓冲区大小需要这么长时间。示例代码在这里:http://pastebin.com/PqisLnLU
相同的代码在 Windows 甚至适用于 Linux 的 Windows 子系统上运行而没有这些奇怪的行为。
谢谢!
最佳答案
您正在看到 Nagle's algorithm 的效果,用于以延迟为代价提高 TCP 吞吐量。
写入相对较小,并且在不久的将来写入更多数据时会被延迟,然后可以将这些数据捆绑在一个 IP 数据包中。当您在发送前使用 select
时,您并没有发送更多(因为发送缓冲区仍然是满的),因此在发送数据包(并且缓冲区被清空)之前有一个显着的延迟。相反,当您不使用 select
时,缓冲区已满,因此当您发送
更多内容时,它会立即通过网络堆栈分流。
(我猜你在同一台机器上运行你的客户端和服务器程序,所以它们之间的“网络”连接实际上是环回接口(interface),它具有相当高的 MTU;否则,Nagle 的算法可能不会在这里成为一个问题)。
当您充分增加缓冲区大小时,在填充缓冲区期间的某个时间点会达到合适的 IP 数据包大小,并且数据会立即通过网络推送(并在收到确认后从发送缓冲区中清除)- 所以没有延迟。
尝试禁用 Nagle 算法(在客户端中):
#include <netinet/tcp.h>
...
value = 1;
if (setsockopt(sockfd, IPPROTO_TCP, TCP_NODELAY, (char*)&value, sizeof(int)))
{
printf("\n Error : SetSockOpt TCP_NODELAY Failed \n");
}
您将看到使用 select
的变体与没有 select
操作的变体一样快。
关于c - 在 Linux 中选择慢速套接字,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/39270419/