Warning: file_get_contents(/data/phpspider/zhask/data//catemap/4/macos/10.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181

Warning: file_get_contents(/data/phpspider/zhask/data//catemap/0/windows/16.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Macos sendto()在OSX上,dgrams不阻止ENOBUFS_Macos_Sockets_Unix_Freebsd - Fatal编程技术网

Macos sendto()在OSX上,dgrams不阻止ENOBUFS

Macos sendto()在OSX上,dgrams不阻止ENOBUFS,macos,sockets,unix,freebsd,Macos,Sockets,Unix,Freebsd,这更多的是一个观察,也是一个关于处理这种情况的最佳方法的建议 我有两个线程,一个只是泵入数据,另一个接收数据,在发送另一个套接字之前做了很多工作。两个线程都通过域套接字连接。这里使用的协议是UDP。我不想使用TCP,因为它是基于流的,这意味着如果队列中的空间很小,我的数据将被分割并发送。这是不好的,因为Iam正在发送不应拆分的数据。因此我使用DGRAM。有趣的是,当send线程通过泵送如此多的数据而压倒recv线程时,在某个点域套接字缓冲区被填满,sendto返回ENOBUFS。我的意见是,如果

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

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

CPU产量法 如果我得到ENOBUFS,我会做一个sched_收益率;因为OSX中没有pthread_。之后,我再次尝试重新发送。如果失败了,我会继续做同样的事情,直到它被采纳。这是不好的,因为我浪费cpu周期只是做一些无用的事情。如果sendto被阻止,我会很高兴的

睡眠法 我试图用sleep1而不是sched_yield来解决同样的问题,但是这没有用,因为sleep会让我的进程进入睡眠状态,而不仅仅是发送线程

这两种方法似乎对我都不起作用,我已经没有选择了。有人能提出处理这个问题的最佳方法吗?是否有一些我不知道的聪明技巧可以减少不必要的cpu周期?顺便说一句,基于这个讨论,手册页上关于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");
}

顺便问一下,您要发送的数据包有多大?

在OS X上发送到实际上是非阻塞的,这是M_DONTWAIT标志。
我建议您使用基于流的连接,并使用recv函数的MSG_WAITALL标志在另一端接收整个数据。如果您的数据具有比简单数据更严格的结构,只需将正确的大小传递给recv即可。如果不只是发送一些固定大小的控制数据包,首先是下一个数据块的大小,然后是数据本身。在接收方,您将等待固定大小的控制数据包,而不是控制数据包中的大小数据。

事实上,据我所知,基于BSD的系统不会像Linux和Solaris那样阻止发送到哪里。Select在这里不起作用,因为在UDP的情况下,TCP中没有可用的发送缓冲区队列,因此Select将不知道no buff。它将始终允许,但将使用ENOBUFS失败。UDP的内核代码如下所示,看起来像BSD上的UDP,OSX sendto不会阻塞。手册页中错误地提到了它。即使选择也无济于事。这是一个关于同一问题的非常有趣的讨论,嗯,我使用select限制OSX下非阻塞UDP套接字的发送速率,这似乎对我很有效。。。当然,这并不能防止数据包稍后被丢弃,例如在网络交换机上,但它确实可以使我的程序以传出UDP缓冲区可以接受的速率发送UDP数据包。对于您的情况,您可能希望只对项目符号进行字节,并将TCP与一些帧逻辑一起使用,例如发送一个数据包大小的报头,然后发送数据包中的数据,以便接收方可以首先读取报头,并在处理itHa之前知道要向缓冲区填充多少字节,我自己在MacOS/X下尝试通过环回设备通过UDP多播套接字发送92MB数据时遇到了同样的问题:现在,我将尝试通过检查ENOBUFS并忽略它来处理它,即循环返回到select。希望这不会导致太多的忙循环…如何生成线程?实际上,它应该适用于POSIX线程。