接收调用返回 Errno 35 (EAGAIN)

8

我有一个套接字,等待接收数据后将其发送进行处理。然后它再次等待接收,但这次它没有收到任何数据,返回-1,并且打印错误号时会显示35(即EAGAIN)。

这只会在MAC OS Lion操作系统上发生,其他操作系统都可以正常运行。

do{
 rc = recv(i, buffer, sizeof(buffer), 0);
 if (rc < 0){
      printf("err code %d", errno); 
 }
 if(rc == 0){ 
      //Code for processing the data in buffer 
      break; 
 } 
      ....
}while(1);

编辑:更正了缩进和errno


(Translated)

无论错误代码是什么,请尽可能发布错误的名称,而不是其数字代码。您标记了您的问题[tag:osx],因此我正在MacOS上查找数字值,35是EAGAIN,但在每个操作系统上都不一定相同。但是,这些名称(大体上)在各个操作系统中具有相同的含义。通过提供错误的名称,您将使一些没有访问MacOS系统的人能够帮助您,以便他们可以自己找出答案。 - Celada
1
"EGAIN" 表示内核没有数据可以提供给您的接收缓冲区。在执行 recv() 之前,在套接字文件描述符上进行 select() 调用如何? - Asblarf
1
你把套接字设置为非阻塞模式了吗? - Nikolai Fetissov
@Celada - 好的,错误代码是35,并打印出EDEADLK作为错误文本。此外,我的调用代码中没有sleep,正如错误描述中所建议的那样。 - VijayKumar
你确定35应该是EDEADLK吗?在我的MacOS系统中,/usr/include/sys/errno.h中将EAGAIN定义为35。 - Celada
显示剩余4条评论
2个回答

8
您可以将套接字设置为非阻塞模式或启用接收超时。以下是来自Mac上的recv(2)
“如果套接字标记为非阻塞,并且接收操作将被阻止,或者已设置接收超时并且在接收数据之前超时到期,则调用失败。”

编辑0:

这次引用来自intro(2)
“11 EDEADLK避免资源死锁。 尝试锁定会导致死锁情况的系统资源。”
“35 EAGAIN资源暂时不可用。 这是一个临时条件,稍后对同一例程的调用可能会正常完成。”
只需使用strerror(3)查找实际问题即可。

感谢您的评论,但它返回的错误是EDEADLK。正如之前的评论所说,我的调用代码中没有睡眠。有什么想法,为什么这只发生在Mac OS Lion而不是Snow Leopard? - VijayKumar
还有一个要补充的是,首先数据被正确地获取到缓冲区中,进行处理后,由于这是一个while循环,它会再次回到recv,在那里出现了errno 35的错误 - 现在对我来说很困惑,因为它指向EDEADLK,而你却说是EAGAIN... - VijayKumar
现在,我给大家提一个开放性问题,因为我暂时忽略了错误而开始运作。我该怎么做这个问题呢?哪个答案应该被标记?我看过很多stackoverflow帖子,用户没有标记正确的答案,导致混淆,而我不想加入其中...欢迎公平建议。 - VijayKumar
哦,显然我的答案是迄今为止唯一永远正确的 :) - Nikolai Fetissov
在我的系统(iOS模拟器)中,我得到35,对于EDEADLKstrerror()报告错误消息。 - Guss
显示剩余2条评论

3
您的套接字处于非阻塞模式。当没有可读取的数据时,EAGAINrecv()(和其他系统调用)的正常返回值。在这个意义上它并不算是一个错误。
如果您想让您的套接字处于非阻塞模式,那么您需要监控它以找出何时有可用数据,并且只在有可用数据时才调用recv()。使用poll()(或kqueue,在FreeBSD和MacOS中特定)进行监视。通常这是在应用程序的主事件循环中完成的。
如果您不希望您的套接字处于非阻塞状态,则应使用fcntl()将其设置为阻塞模式:
flags = fcntl(i, F_GETFL, 0); /* add error checking here, please */
flags &= ~O_NONBLOCK;
fcntl(i, F_SETFL, flags); /* add more error checking here! */

但是你应该知道,套接字(以及所有文件描述符)的默认阻塞状态是阻塞式,所以如果您的套接字处于非阻塞模式,则意味着有人或某些程序已经手动将其设置为非阻塞。

在阻塞模式下,recv调用将被阻塞并等待更多数据,而不是返回EAGAIN (或与EAGAIN相同的EWOULDBLOCK)。


阻塞模式是默认设置。如果他不想让它成为非阻塞模式,他应该删除设置的代码,而不是添加更多代码来取消设置。 - user207421
谢谢您的评论Celada,但是错误35将我指向EDEADLK而不是EAGAIN,而在我的情况下,EAGAIN应该是41?是否存在错误代码不匹配的问题? - VijayKumar
@EJP 是的。我是从这样一种观点考虑的,即文件描述符可能来自某种始终返回非阻塞套接字的库。这可以解释为什么您的套接字可能是非阻塞的,而您却不知道它。我知道这很牵强。无论如何,原帖已经澄清,它是有意为之的。 - Celada
我知道这听起来很疯狂,但是errno是否取决于操作系统?因为在MAC OS Snow Leopard上,这段代码可以正常工作,没有任何问题,只有在Lion上才出现了这个问题...这只是一个猜测,如果这真的非常疯狂,请别打我... - VijayKumar
你是正确的@Celada,它确实指向了MAC OS Snow Leopard中的EAGAIN。 - VijayKumar

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接