gpt4 book ai didi

macos - sendto() dgrams 不会阻塞 OSX 上的 ENOBUFS

转载 作者:行者123 更新时间:2023-12-04 15:59:21 31 4
gpt4 key购买 nike

这更多是一种观察,也是对处理这种情况的最佳方法的建议。

我有两个线程,一个只是泵入数据,另一个接收数据并在发送另一个套接字之前做很多工作。两个线程都通过域套接字连接。这里使用的协议(protocol)是 UDP。我不想使用 TCP,因为它是基于流的,这意味着如果队列中的空间很小,我的数据就会被拆分和发送。这很糟糕,因为我正在发送不应该拆分的数据。因此我使用了 DGRAM。有趣的是,当发送线程通过抽取如此多的数据压倒了接收线程时,在某些时候域套接字缓冲区被填满并且 sendto() 返回 ENOBUFS。我认为如果发生这种情况, sendto() 将阻塞,直到缓冲区可用。这将是我想要的行为。然而,情况似乎并非如此。我以一种相当奇怪的方式解决了这个问题。

  • CPU 产量方法
    如果我得到 ENOBUFS,我会执行 sched_yield();因为 OSX 中没有 pthread_yield() 。之后,我尝试再次重新发送。如果失败了,我会继续做同样的事情,直到它被采取。这很糟糕,因为我只是在做一些无用的事情而浪费 CPU 周期。如果 sendto() 被阻止,我会很高兴。
  • sleep 方式
    我尝试使用 sleep(1) 而不是 sched_yield() 来解决相同的问题,但这没有用,因为 sleep() 会使我的进程进入休眠状态,而不仅仅是发送线程。

  • 他们两个似乎都不适合我,而且我已经没有选择了。有人可以建议处理这个问题的最佳方法是什么吗?是否有一些我不知道的巧妙技巧可以减少不必要的 CPU 周期?顺便说一句,根据这个讨论 http://lists.freebsd.org/pipermail/freebsd-hackers/2004-January/005385.html,手册页上关于 sentto() 的内容是错误的

    内核中的 Upd 代码:
    The udp_output function in /sys/netinet/udp_usrreq.c, seems clear:

    /*
    * Calculate data length and get a mbuf
    * for UDP and IP headers.
    */
    M_PREPEND(m, sizeof(struct udpiphdr), M_DONTWAIT);
    if (m == 0) {
    error = ENOBUFS;
    if (addr)
    splx(s);
    goto release;
    }

    最佳答案

    我不确定为什么 sendto() 没有阻止你……但你可以在每次调用 sendto() 之前尝试调用这个函数:

    #include <stdio.h>
    #include <sys/select.h>

    // Won't return until there is space available on the socket for writing
    void WaitUntilSocketIsReadyForWrite(int socketFD)
    {
    fd_set writeSet;
    FD_ZERO(&writeSet);
    FD_SET(socketFD, &writeSet);
    if (select(socketFD+1, NULL, &writeSet, NULL, NULL) < 0) perror("select");
    }

    顺便说一句,您尝试发送的数据包有多大?

    关于macos - sendto() dgrams 不会阻塞 OSX 上的 ENOBUFS,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/16555101/

    31 4 0
    Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
    广告合作:1813099741@qq.com 6ren.com