【问题标题】:Can't turn TCP_NODELAY OFF无法关闭 TCP_NODELAY
【发布时间】:2013-02-24 01:06:09
【问题描述】:

我正在使用 Boost asio 发送 TCP 消息。我设置了 NO_DELAY 选项,因为这是一个“实时”控制系统。我看到使用 Wireshark 在消息中设置了 PSH 标志。我对性能感到满意,它按预期工作。

出于兴趣,我决定关闭 NO_DELAY 并测量性能差异。

我交换了我现有的代码:

m_tcpSocket.open(boost::asio::ip::tcp::v4());
boost::asio::ip::tcp::no_delay noDelayOption(true);
m_tcpSocket.set_option(noDelayOption);

// snip create endpoint
m_tcpSocket.connect(m_tcpServerEndpoint);

// snip build message
m_tcpSocket.send(boost::asio::buffer(pDataBuffer, size));

boost::asio::ip::tcp::no_delay noDelayOption(false);
m_tcpSocket.set_option(noDelayOption);

我仍然看到设置了 PSH 标志。

我还尝试删除 set_option 代码,但仍然看到它已设置。

在 Wireshark 中我看到了:

104 - 105  SYN
105 - 104  SYN, ACK
104 - 105  ACK
104 - 105  PSH, ACK + my message
105 - 104  ACK

其中 104 和 105 是我的 2 台 PC 的 IP 地址。 我也很惊讶包含我的数据的消息有一个 ACK​​。

如何关闭 NO_DELAY?

【问题讨论】:

    标签: boost-asio delay nagle


    【解决方案1】:

    您的代码看起来好像正确地将TCP_NODELAY 设置为打开或关闭。要将TCP_NODELAY 设置为关闭,请使用:

    socket.set_option(boost::asio::ip::tcp::no_delay(false));
    

    TCP RFC 将 PSH 定义为推送功能。简而言之,它是一个标志,通知接收者所有数据都已发送,因此将数据向上转发到协议栈。 Boost.Asio maps 其 API 到 BSD 套接字,而 BSD 套接字不提供控制 PSH 标志的方法。这通常由协议栈中的内核在清除其缓冲区时处理。

    来自TCP/IP Illustrated

    该标志通常用于指示发送数据包一侧的缓冲区已与发送数据包一起被清空。也就是说,当设置了 PSH 位域的数据包离开发送方时,发送方就没有更多的数据可以发送了。

    [...]

    推送(接收方应尽快将此数据传递给应用程序 - 不可靠地实现或使用)。

    【讨论】:

    • 谢谢,我确实需要知道打开或关闭 TCP_NODELAY 的设置,因此我将其标记为正确答案。我认为设置和推送标志之间存在直接关联,现在明白没有。我现在假设,如果我有大量数据要发送并且 TCP_NODELAY 关闭,那么套接字可能会将数据分解为多个数据包,并且我可以期望这些数据包中的最后一个数据包设置了 PSH 标志。
    【解决方案2】:

    NO_DELAY 不会更改发送给对等方的标志。它改变了内核的缓冲算法。谷歌关于 Nagle 算法的更多了解。

    【讨论】:

    • 我一直在阅读有关 Nagle 以及 NO-DELAY 的影响的信息,尽管我知道您不能依赖您在 Internet 上找到的所有内容,但我认为推送标志已设置为对端也没有延迟。我是不是搞错了?
    • @Ant Nagle 是延迟发送,对端无关。
    • 好的,我现在明白了。我认为 NO_DELAY 和 PSH 标志之间存在直接关联。
    猜你喜欢
    • 2013-03-23
    • 1970-01-01
    • 1970-01-01
    • 2016-09-20
    • 2018-06-18
    • 2010-11-08
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多