【问题标题】:Raw Socket Receive Buffer原始套接字接收缓冲区
【发布时间】:2014-10-14 02:26:24
【问题描述】:

我们目前正在测试基于 IP 的电信应用程序。我们打开一个 Raw Socket 并从远程端接收消息(msgrate@750+msgs/second 大约大小为 180 字节,不包括 IP)。

在原始套接字的顶部有一个称为 SCTP(就像 TCP)的层,它时不时地指示它丢失了一些数据包。现在,我们在接收节点上运行 Wireshark,我们可以在 Wireshark 中看到该数据包。

在我看来,套接字的接收缓冲区很小,导致 IP(?) 丢弃消息。但是,IP Pegs(netstat -sv) 显示没有丢弃的数据包。我们尝试将套接字接收队列设置为 40000,但没有任何成功。

如果我们应该配置 IP 层的哪个选项(如果有的话),或者我们需要设置任何特定的套接字选项,我将不胜感激。

【问题讨论】:

    标签: sockets queue


    【解决方案1】:

    感谢您的意见。但是,我们已经能够“解决”这个问题。 之前,我描述了我们如何阅读消息。 一旦 select 返回,我们运行一个循环(根据要读取的原始消息的数量,在我们的例子中大于 1)。 1) 我们调用 ioctl(FIONREAD) 来查找要读取的字节数; 2) 通过调用 recvfrom 读取那么多字节 3)将字节发送给用户 4) 再次进入循环并调用 ioctl(FIONREAD) 然后重复这些步骤

    但是,在第 4 点,ioctl(FIONREAD) 使用返回 0。我们的代码进行了防御性检查。预期,来自 ioctl(FIONREAD) 的 0 字节意味着发送者发送了一个有效负载为 0 的 IP 标头。因此,它使用调用 recvfrom(bytes to read=0) 来清除 IP 标头,以免 select 再次设置。

    在时间 t0,ioctl(FIONREAD) 返回 0 作为要读取的字节数 在时间 t1,调用 recvfrom(bytes to read=0)。 有时,在 t0 和 t1 之间,实际数据用于在套接字接收队列中排队并用于在我们调用 recvFrom(bytes=0) 时被丢弃。

    设置,rawMsgsToRead=1 的数量已经“解决”了这个问题。但是,我的猜测是它会影响我们的表现。他们是否有任何 ioctl 调用可以区分队列中的八位字节为 0 和负载为 0 的 IP 标头

    【讨论】:

    • 很高兴您解决了问题。您应该创建一个关于您添加的关于区分队列中的八位字节为 0 和有效负载为 0 的 IP 标头的问题的新问题。问候
    • 其实经过进一步分析,我得出的结论是,调用ioctl(FIONREAD) 查找未决字节数是系统调用过多。我将代码更改为只执行一个 recv(在 UDP/Raw 数据包的情况下),并将缓冲区大小设置为我们期望的最大值。完成后,我不再需要担心负载为 0 的 IP 标头。不过感谢您的帮助。它让我朝着正确的方向思考。
    【解决方案2】:

    我有几个问题和一些事情要考虑。 1)您正在使用哪种 SCTP 实现以及在哪个操作系统上。一些 SCTP 实现比其他实现更健壮。 2) SCTP 是否否定地确认丢弃的数据包?在wireshark 中搜索gapack。 3)你在wireshark中看到丢弃的数据包你确定这些不是重传吗? 4)wireshark监控系统在哪里?如果它与您的应用程序不在同一条线上,那么它可能会看到您的应用程序没有看到的消息。 5) SCTP 给出的具体指示是什么?

    如果您认为 IP 套接字 rx 缓冲区溢出,那么您可以考虑减小 SCTP RX 窗口的大小;这通常可以在 sctp 堆栈中进行配置。 Rx 窗口限制了等待确认的未完成数据量,因此限制了 IP 缓冲区中的数据量。 您还可以尝试提高 SCTP 任务的优先级,以便它更快地从 IP 缓冲区中读取消息(这可能是最容易尝试的事情,我认为这是一件好事)。

    问候

    【讨论】:

    • 我们基本上是堆栈供应商,所以 SCTP 实现是我们自己的。操作系统是Linux。是的,wireshark 确实提到了 Gap Ack 块中的数据包。在接收节点运行的 Wireshark 会显示数据包,但它们从未到达 SCTP。我们在 SCTP 层下面有一个 Socket 包装器。在 SCTP 上,我们打印收到的 TSN,在 Wrapper 上,我们打印了 IP 标头中的标识字段。我可以清楚地看到 IP 数据包没有到达 Wrapper(因此没有到达 SCTP)。
    • 我已将 IP 的 txqueuelen 和 receviequeue len 增加到 10000。尝试通过将 setsockopt 调用为 40000 来增加套接字接收缓冲区,但无济于事。 IP 挂钩不显示任何丢弃的消息。任何想法将不胜感激。
    • 你在哪家公司工作?您是否尝试过提高 SCTP 任务的优先级并减小 SCTP rx 窗口的大小?丢失的块是在单独的 sctp 消息中传输还是捆绑在一起?问题是否仅在高负载时发生?你怎么知道丢失的消息没有命中 IP 包装器?问候
    • 我为 CCPU(以前的 Trillium)工作。丢失的块是 1 个单个 IP 数据包(但捆绑的 SCTP 块)。是的,问题发生在 750+msg 速率。我们的 Wrapper 是关于 IP 的一层。因此,IP 将数据包提供给我们的 Wrapper(基本上是套接字接收队列中的队列),然后我们的 wrapper 将其拾取。我们确信,通过调试打印,我们没有收到数据包。我们目前正在提高 SCTP Taks 的优先级。我不确定您所说的减小 SCTP rx 窗口大小是什么意思。
    • 一个 sctp 关联维护一个有限的缓冲区,用于保存从对等方接收到的数据,然后再将其传递给 SCTP 用户。这个大小称为 rx_window 并且在wireshark 跟踪中被视为广告接收窗口'awnd'? linux 内核实现使用 128KB 的默认 rx 窗口。您使用的是哪个 Linux 内核版本?这可能很重要。
    猜你喜欢
    • 1970-01-01
    • 2018-11-08
    • 1970-01-01
    • 1970-01-01
    • 2013-02-16
    • 2014-08-17
    • 2011-11-15
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多