在Linux上设置套接字发送缓冲区大小的正确方法是什么?

4

我有一个NIO服务器,接收小的客户端请求,并产生大约1兆字节的响应。服务器使用以下方法来接受新的客户端:

SocketChannel clientChannel = server.accept();
clientChannel.configureBlocking(false);
clientChannel.socket().setSendBufferSize(2 * 1024 * 1024);

我接下来会记录一条“客户端已连接”的日志,其中包括clientChannel.socket().getSendBufferSize()的结果。

在Windows上,该设置将客户端套接字的发送缓冲区大小从8k更改为2兆字节。但是在Linux上,套接字显示其发送缓冲区为131,071字节。

这会导致性能不佳,因为我的clientChannel.write每次只写入128k的数据,所以需要7次以上的操作才能将所有数据写入。在Windows上,setSendBufferSize的更改显著提高了性能。

Linux似乎被配置为允许大型套接字发送缓冲区:

$ cat /proc/sys/net/ipv4/tcp_wmem
4096    16384   4194304

这个问题说在调用accept之前需要设置SendBufferSize:http://stackoverflow.com/questions/12749174/can-i-increase-the-socket-send-buffer-size-if-the-send-fails-due-to-buffer-full。但是在调用accept之前我没有clientChannel。 - Ted Graham
我对那个问题的评论涉及到接收缓冲区大小。你可以随时设置发送缓冲区大小。 - user207421
2个回答

2
平台可以自由调整请求的缓冲区大小,这就是Linux所做的。除了通过内核配置来调整最大值之外,您无法做任何事情。
请注意,我在您链接的问题中关于设置缓冲区大小> 64k的评论仅适用于接收缓冲区,而不是发送缓冲区,因为接收缓冲区大小会影响窗口缩放选项,因此需要在套接字连接之前设置,以固定窗口比例。
我不明白为什么要求“更多的传递”会导致如此重大的性能差异,以至于您甚至要问这个问题。在我看来,您最好将接收器的窗口大小向上调整,并在连接之前执行此操作。

增加客户端的接收缓冲区对Windows客户端有效,但并没有导致服务器增加其发送缓冲区。当服务器有1兆字节要发送且只有128k的发送缓冲区时,需要再进行7次clientChannel.write调用才能将所有数据发送完毕。我应该继续在循环中调用write吗? - Ted Graham
增加接收方的接收缓冲区对服务器的发送缓冲区没有影响,也没有任何地方说明。如果您处于阻塞模式,则只需进行单个写操作,否则您必须循环执行。 - user207421
1
看起来net.core.wmem_max将我限制在128k。遵循http://www.cyberciti.biz/faq/linux-tcp-tuning/上的指示,允许我的Java程序请求2兆发送缓冲区。 - Ted Graham

-2

子类化ServerSocket对ServerSocketChannel没有影响,而且整个操作在设置发送缓冲区大小时也没有任何区别。 - user207421

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接