Java TCP_NODELAY 如何影响连续的 write() 调用?

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/18091523/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-08-11 22:19:37  来源:igfitidea点击:

How does TCP_NODELAY affect consecutive write() calls?

javasocketsnetworkingtcp

提问by AyCe

TCP_NODELAY is an option to enable quick sending of TCP packets, regardless of their size. This is very useful option when speed matters, however, I'm curious what it will do to this:

TCP_NODELAY 是启用快速发送 TCP 数据包的选项,无论其大小如何。当速度很重要时,这是非常有用的选项,但是,我很好奇它会对此做什么:

Socket socket = [some socket];
socket.setTcpNoDelay(true);
OutputStream out = socket.getOutputStream();
out.write(byteArray1);
out.write(byteArray2);
out.write(byteArray3);
out.flush();

I tried to find what flush actually does on a SocketOutputStream, but as far as I know now, it doesn't do anything. I had hoped it would tell the socket "send all your buffered data NOW", but, unfortunately, no it doesn't.

我试图找出 flush 在 a 上实际做了什么SocketOutputStream,但据我现在所知,它没有做任何事情。我曾希望它会告诉套接字“现在发送所有缓冲的数据”,但不幸的是,它没有。

My question is: are these 3 byte arrays sent in one packet? I know you don't have much control over how TCP constructs a network packet, but is there any way to tell the socket to (at least try to) pack these byte arrays, so network overhead is avoided? Could manually packing the byte arrays and sending them in one call to writehelp?

我的问题是:这些 3 字节数组是在一个数据包中发送的吗?我知道您对 TCP 如何构建网络数据包没有太多控制权,但是有什么方法可以告诉套接字(至少尝试)打包这些字节数组,从而避免网络开销?可以手动打包字节数组并在一次调用中发送它们以提供write帮助吗?

采纳答案by user207421

My question is: are these 3 byte arrays sent in one packet?

我的问题是:这些 3 字节数组是在一个数据包中发送的吗?

As you have disabled the Nagle algorithm, almost certainly not, but you can't be 100% sure.

由于您禁用了 Nagle 算法,几乎可以肯定不会,但您不能 100% 确定。

I know you don't have much control over how TCP constructs a network packet, but is there any way to tell the socket to (at least try to) pack these byte arrays

我知道您对 TCP 如何构建网络数据包没有太多控制权,但是有什么方法可以告诉套接字(至少尝试)打包这些字节数组

Yes. Don'tdisable the Nagle algorithm.

是的。不要禁用 Nagle 算法。

so network overhead is avoided? Could manually packing the byte arrays and sending them in one call to write help?

所以避免了网络开销?可以手动打包字节数组并在一次调用中发送它们以编写帮助吗?

Yes, or simpler still just wrap the socket output stream in a BufferedOutputStreamand call flush()when you want the data to be sent, as per your present code. You are correct that flush()does nothing on a socket output stream, but it flushes a BufferedOutputStream.

是的,或者更简单的仍然是将套接字输出流包装在 a 中,BufferedOutputStreamflush()在您想要发送数据时调用,根据您当前的代码。你是flush()对的,在套接字输出流上什么都不做,但它刷新了BufferedOutputStream.

回答by xaxxon

Could manually packing the byte arrays and sending them in one call to write help?

可以手动打包字节数组并在一次调用中发送它们以编写帮助吗?

Yes, send them all in a single call to write. This will maximize the chances that your bytes will be sent in a single packet.

是的,在一次调用中将它们全部发送到 write。这将最大限度地增加您的字节在单个数据包中发送的机会。

Of course, you can never know, since there are too many variables involved - different OSs and lots of different networking gear between you and your peer, but if you give the OS the ability to pack everything together, it will generally try to.

当然,您永远无法知道,因为涉及的变量太多——您和您的同行之间有不同的操作系统和许多不同的网络设备,但是如果您让操作系统能够将所有内容打包在一起,它通常会尝试这样做。

If you disable nagle and make seperate system calls (remember, the OS controls the sockets, not your appliation or java), you're asking the OS to send them individually. The OS has no idea you're about to call write again with some more data.

如果您禁用 nagle 并进行单独的系统调用(请记住,操作系统控制套接字,而不是您的应用程序或 Java),您是在要求操作系统单独发送它们。操作系统不知道您将使用更多数据再次调用 write。