C语言 UDP 和套接字,recvfrom() 返回 -1 并且资源暂时不可用

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/2379430/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-09-02 04:44:13  来源:igfitidea点击:

UDP and sockets, recvfrom() returning -1 and resource temporarily unavailable

csocketsclientudp

提问by Fantastic Fourier

I have a client and a server communicating with datagrams (UDP) in C. The client sends 5 msgs and upon receiving msgs, server sends msgs back. Receiving and sending messages are great until client has finished receiving the msgs. After server sending all msgs back, it terminates using close(). so recvfrom() from client should return 0, right?

我有一个客户端和一个服务器,与 C 中的数据报 (UDP) 通信。客户端发送 5 条消息,收到消息后,服务器将消息发回。在客户端完成接收消息之前,接收和发送消息很好。服务器发送回所有消息后,它使用 close() 终止。所以来自客户端的 recvfrom() 应该返回 0,对吗?

Assuming recvfrom() should return 0 upon close() from server side, it returns -1 instead, with error Resource temporarily unavailable. Is this resource reference to closed socket from server? Or is it for something else entirely different like running out of buffer or something (which i don't think is true)?

假设 recvfrom() 应该在服务器端的 close() 返回 0,它返回 -1,错误资源暂时不可用。这个资源引用是从服务器关闭的套接字吗?或者是因为其他完全不同的事情,比如缓冲区用完或其他什么(我认为这不是真的)?

Assuming my assumption was wrong and -1 is returned because server terminated, I probably should handle the error with

假设我的假设是错误的并且由于服务器终止而返回 -1,我可能应该使用

if(SOMEMACRO)
   do something 

How do I find out what SOMEMACROis? I print out the error but it says resource temp unavailable and recvfrom() description doesn't mention about unavilable resource..?

我怎么知道SOMEMACRO是什么?我打印出错误,但它说资源临时不可用并且 recvfrom() 描述没有提到不可用的资源..?

Btw, this is a non blocking socket, if that makes any difference since i read that if O_NONBLOCK is set and no msgs are available, it would set errno to EAGAIN or EWOULDBLOCK. O_NONBLOCK isn't set but MSG_DONTWAIT is set. Are they basically the same thing where O_NONBLOCK is for general file descriptors and MSG_DONTWAIT is socket specific??

顺便说一句,这是一个非阻塞套接字,如果这有什么不同,因为我读到如果设置了 O_NONBLOCK 并且没有可用的消息,它会将 errno 设置为 EAGAIN 或 EWOULDBLOCK。O_NONBLOCK 未设置但 MSG_DONTWAIT 已设置。它们是否与 O_NONBLOCK 用于一般文件描述符而 MSG_DONTWAIT 是特定于套接字的东西基本相同?

My brain isn't working all that great now, if someone could enlighten me and clarify what my confusion is about, i would deeply appreciate it. Thanks!

我的大脑现在工作得不太好,如果有人能启发我并澄清我的困惑是什么,我将不胜感激。谢谢!

回答by bdk

UDP is a stateless protocol, unlike TCP which is connection oriented. Your receiving code will not know whether or not the sender has closed its socket, it only knows whether or not there is data waiting to be read. According to the man page for recvfrom on Linux:

UDP 是一种无状态协议,与面向连接的 TCP 不同。你的接收代码不会知道发送者是否关闭了它的套接字,它只知道是否有数据等待读取。根据 Linux 上 recvfrom 的手册页:

If no messages are available at the socket, the receive calls wait for a message to arrive, unless the socket is nonblocking (see fcntl(2)) in which case the value -1 is returned and the external variable errno set to EAGAIN.

如果套接字上没有可用消息,则接收调用将等待消息到达,除非套接字是非阻塞的(请参阅 fcntl(2)),在这种情况下,将返回值 -1 并将外部变量 errno 设置为 EAGAIN。

This seems to be what is happening for you

这似乎是你正在发生的事情

Edit: Note that "resource temporarily unavailable" and EAGAIN are the same error, one is just the user friendly descption vs the define name. Basically its just telling you that you are trying to read from the socket and there is no data to read

编辑:请注意,“资源暂时不可用”和 EAGAIN 是相同的错误,一个只是用户友好的描述与定义名称。基本上它只是告诉您您正在尝试从套接字读取并且没有要读取的数据

回答by Vlad

After your have closed the socket it still lingers around for sometime. Usually about two minutes or so. To avoid this, use SO_REUSEADDR socket option.

在您关闭插座后,它仍然会徘徊一段时间。通常大约两分钟左右。为避免这种情况,请使用 SO_REUSEADDR 套接字选项。

Here are some references for you.

这里有一些参考资料供您参考。

http://msdn.microsoft.com/en-us/library/ms740476%28VS.85%29.aspxhttp://docs.hp.com/en/B2355-90136/ch03s01.html

http://msdn.microsoft.com/en-us/library/ms740476%28VS.85%29.aspx http://docs.hp.com/en/B2355-90136/ch03s01.html

And here is an example, scroll down to udp_listen function:

这是一个示例,向下滚动到 udp_listen 函数:

http://www.codase.com/search/display?file=L2dlbnRvbzIvdmFyL3RtcC9yZXBvcy9jb2Rhc2UuYy9zbGlycC0xLjAuMTYvd29yay9zbGlycC0xLjAuMTYvc3JjL3VkcC5j&lang=c&off=15730+15796+

http://www.codase.com/search/display?file=L2dlbnRvbzIvdmFyL3RtcC9yZXBvcy9jb2Rhc2UuYy9zbGlycC0xLjAuMTYvd29yay9zbGlycC0xLjAuMTYvc37CjL3RtcC9yZXBvcy9jb2Rhc2UuYy9zbGlycC0xLjAuMTYvd29yay9zbGlycC0xLjAuMTYvc37CjL3+1Vc5c7CjL3+1