【问题标题】:How does TCP_NODELAY affect consecutive write() calls?TCP_NODELAY 如何影响连续的 write() 调用?
【发布时间】:2013-08-06 22:19:34
【问题描述】:

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();

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

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

【问题讨论】:

  • "TCP_NODELAY .. 在速度很重要时很有用。" 。当 响应性 很重要(发送一个字节以便尽快接收)时,它很有用。 TCP_NODELAY 可以通过发送聚合数据相对无效降低整体吞吐量。缓冲很好:随时随地。恕我直言...
  • 建议:获取wireshark 的副本并跟踪为几个测试套接字程序实际发送的数据包。
  • 是的,我就是这个意思。 ;-) 我知道它效率低下,但就我而言,响应能力 比等待足够的数据更重要。但是,对于问题所在的情况,我想对其进行优化,因为发送单字节数组没有多大意义,重要的是它们的内容。
  • @AyCe:然后一次性发送所有数据。将它们组合起来需要额外的几微秒,这是假设缓冲区不小。与网络流量需要多长时间相比,这段时间微不足道。
  • @cHao 这将是我目前的方法,但我很好奇是否有更好的方法,搜索没有任何结果,所以我问了这个问题。

标签: java sockets networking tcp


【解决方案1】:

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

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

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

是的。 不要禁用 Nagle 算法。

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

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

【讨论】:

  • 正如我在评论中所述,我的应用程序需要 TCP_NODELAY,因此禁用不是我的选择。我实际上已经使用BufferedOutputStream 发送,这是否保证数据只发送一次flush() 被调用?
  • 是的,如果BufferedOutputStream 缓冲区大到足以容纳所有待处理的数据。 (默认情况下为 8k。)但是,如果您希望同时接收数据,请三思。对此没有任何保证。您仍然需要在接收器处循环,直到获得所需的一切,或者如果您知道预期的长度,请使用DataInputStream.readFully()
  • 好的,很好!当然,我知道我不能像使用 UDP 那样将它作为“数据包”接收。所有这些字节数组都是单个消息,但它们只有在收到最后一个消息后才有意义。所以将它们作为单个数据包发送是没有意义的。
【解决方案2】:

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

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

当然,你永远不会知道,因为涉及的变量太多 - 不同的操作系统和你和你的同伴之间的许多不同的网络设备,但如果你让操作系统能够将所有东西打包在一起,它通常会尝试到。

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

【讨论】:

  • 感谢您的信息!我正在合并字节数据包,这似乎工作得很好。
  • @AyCe 如果您认为这比其他答案更好地回答了您的问题,如果您能切换接受的答案,我将不胜感激。
  • 您的回答很好,您解释了 Sockets 的 OS/Java 分离,并回答了我的第二个问题,同时回答了我的主要问题(如果这些 3 字节数组可能会在一个数据包)也间接地。 EJP 也回答了这两个问题,但也给出了使用BufferedOutputStream 的建议,所以我觉得这个答案更完整:)
  • @AyCe 好的,没问题。
  • 要求操作系统单独发送它们,但仍不能保证它会。
猜你喜欢
  • 2021-03-15
  • 1970-01-01
  • 1970-01-01
  • 2012-01-03
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多