c - 在 Linux 中选择慢速套接字

标签 c linux sockets

我有一个奇怪的问题,即 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/

相关文章:

php - Websocket:如何在 C 中编码文本以发送给客户端

linux - 在 bash 脚本中实现一个简单版本的查找

java - 尝试传递 InputStream 时出现 StreamCorruptedException

c++ - c socket多次调用read

java - 如何改进从 Socket 读取 XML 的方式

强制转换/访问相同的内存是 C 中的不同变量

c - 如何求两个集合的笛卡尔积

c++ - 从函数返回字符串....限制?

c - 具有信号强度的 Linux 蓝牙 l2ping(没有连接?)

linux - 仅当文件存在于 shell 脚本中时才移动