【问题标题】:sendto on Tru64 is returning ENOBUFTru64 上的 sendto 正在返回 ENOBUF
【发布时间】:2010-05-11 10:46:42
【问题描述】:

我目前在 Tru64 上运行一个旧系统,其中涉及使用 sendto() 函数的大量 UDP 套接字。套接字在我们的代码中用于向/从各种进程发送消息,然后最终发送到远程连接的胖客户端应用程序。有时,胖客户端的套接字会卡住,这可能会导致其中一些消息堆积起来。我的问题是如何确定当前缓冲区大小,以及如何确定最大消息缓冲区。下面的代码给出了我如何设置端口和使用 sendto 函数的 sn-p。

/* need to adjust the maximum size we can send on this */
/* as it needs to be able to cope with the biggest     */
/* messages we send                                    */

lenlen = sizeof(len) ;

/* allow double for when the system is under load */
int                 lenlen, len ;
lenlen = sizeof(len) ;
len = 2 * 32000;

msg_socket = socket( AF_UNIX,SOCK_DGRAM, 0);

 result = setsockopt(msg_socket, SOL_SOCKET, SO_SNDBUF, (char *)&len, lenlen) ;

    result = sendto( msg_socket,
                         (char *)message,
                         (int)message_len,
                         flags,
                         dest_addr,
                         addrlen);

注意。我们已将此应用程序移植到 Linux,但问题似乎并未出现。

任何帮助将不胜感激。

问候

【问题讨论】:

    标签: linux unix sockets


    【解决方案1】:

    UDP 发送缓冲区大小与 TCP 不同 - 它只是限制数据报的大小。引用史蒂文斯 UNP 卷。 1:

    ... UDP 套接字有一个发送缓冲区大小(我们可以使用SO_SNDBUF 套接字选项更改,第 7.5 节),但这只是可以写入套接字的最大 UDP 数据报的上限。如果应用程序写入的数据报大于套接字发送缓冲区大小,则返回EMSGSIZE。由于 UDP 不可靠,它不需要保留应用程序数据的副本,也不需要实际的发送缓冲区。 (应用程序数据通常在向下传递协议栈时被复制到某种形式的内核缓冲区中,但在数据传输后,该副本会被数据链路层丢弃。)
    UDP 只是在前面加上 8 字节的报头并将数据报传递给 IP。 IPv4 或 IPv6 预先添加其标头,通过执行路由功能确定传出接口,然后将数据报添加到数据链路输出队列(如果它适合 MTU)或将数据报分段并将每个片段添加到数据链路输出队列。如果 UDO 应用程序发送大数据报(比如 2,000 字节数据报),则与 TCP 相比,出现碎片的可能性要高得多。因为 TCP 将应用程序数据分成 MSS 大小的块,这在 UDP 中没有对应物。
    write 到 UDP 套接字的成功返回告诉我们数据报或数据报的所有片段都已添加到数据链路输出队列中。如果队列中没有数据报或其片段之一的空间,则ENOBUFS 通常会返回给应用程序。
    不幸的是,一些实现不返回这个错误,给应用程序没有指示数据报被丢弃甚至没有被传输。

    最后一个脚注需要注意 - 但看起来 Tru64 在manual page 中列出了这个错误代码。

    不过,正确的做法是在应用程序本身中对未完成的消息进行排队,并在每次系统调用后仔细检查返回值和errno。这仍然不能保证交付(因为 UDP 接收器可能会在没有通知发送者的情况下丢弃数据包)。用netstat -s在两边/所有边检查UDP数据包丢弃计数器,看看它们是否在增长。除了切换到 TCP 或实现自己的超时/确认和重新传输逻辑之外,真的没有其他办法。

    【讨论】:

      【解决方案2】:

      您可能应该使用某种拥塞控制来避免网络过载。到目前为止,最简单的方法是使用 TCP 而不是 UDP。

      它在 Linux 上失败的频率较低,因为 UDP 套接字在 Linux 上等待本地网络接口队列中的空间(除非您将它们设置为非阻塞)。但是,对于任何操作系统,如果溢出队列不在本地系统中,数据包将被静默丢弃。

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 1970-01-01
        • 2014-05-23
        • 2012-08-02
        • 2014-07-02
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        相关资源
        最近更新 更多