sendto: 资源暂时不可用(错误码11)

5

我在使用sendto时遇到了问题。

我有一个接收者,使用recvfrom接收UDP数据包,然后使用sendto回复发送者。

不幸的是,我遇到了错误码11(资源暂时不可用)。我正在使用两个套接字。

第一个数据包确实被发送成功,但之后的都没有发出:

sendto :: 成功

错误:0。

sendto :: 资源暂时不可用

错误:11。

sendto :: 资源暂时不可用

...

这是我的代码片段:

    int sockfd, sockSend;

    if ((sockfd = socket(AF_INET, SOCK_DGRAM, 0)) < 0)
            perror("socket");

    if ((sockSend = socket(AF_INET, SOCK_DGRAM, 0)) < 0)
            perror("socket");

    if (fcntl(sockfd, F_SETOWN, getpid()) < 0) {
            perror("fcntl"); 
    }
    if (fcntl(sockfd, F_SETFL, O_RDONLY | O_NONBLOCK | FASYNC) < 0) {
            perror("fcntl"); 
    } 

    if (bind(sockfd, (struct sockaddr *) &serv_addr, sizeof(serv_addr))
                    < 0)
            perror("bind");

在SIGIO处理程序中:

    len = sizeof(recv_addr);
    char buffer[payload];
    bzero(buffer, payload);
    n = recvfrom(sockfd, buffer, payload, MSG_DONTWAIT, (struct sockaddr *)&recv_addr, &len);

    while (n > 0) {

                            sprintf(response, "%d\n%d\n%d\n", items, target_buf, pb_sp);          
                            sendto(sockSend, response, strlen(response), 0, (struct sockaddr *) &recv_addr, sizeof(recv_addr));
                            // sleep(1);

                            perror("sendto :");
                            printf("error: %d.\n", errno);

     }

这个问题可能是因为端口仍然繁忙,需要等待一段时间才能重新使用。我已经尝试更改端口,但没有帮助。

更新:如果注释掉sleep(1),则数据包实际上会被发送!

非常感谢您的帮助。


你是否正在使用相同端口的两个套接字?如果是,原因是什么? - penguin359
也许使用 SO_REUSEADDR 会有所帮助。或者你可以保持端口开放而不是打开和关闭它,或者每次使用一个新的随机分配的端口号,如果这是可行的话。 - R.. GitHub STOP HELPING ICE
我已经添加了更多的代码。我有两个套接字,但只有一个绑定到一个端口(用于在特定端口接收数据),另一个可以从任何端口发送数据。 - Jary
我刚刚尝试使用了SO_REUSEADDR,但没有帮助。你说的保持端口假定是什么意思?我认为它没有被关闭,因为我没有调用close()函数。 - Jary
我意识到使用sleep()可以解决问题,但我不确定如何在没有它的情况下修复这个问题。 - Jary
2个回答

11

您遇到的错误:

EAGAIN 或 EWOULDBLOCK:套接字已标记为非阻塞模式,并且请求的操作将阻塞。 POSIX.1-2001 允许返回任一错误,并不要求这些常量具有相同的值,因此便携式应用程序应检查两种可能性。

您将套接字设置为非阻塞模式(O_NONBLOCK)。 套接字仍在忙于发送上一个消息。 在第一个消息完成发送之前,您无法发送另一个消息。 这就是为什么休眠有所帮助。

请勿将其设置为非阻塞模式,或在 select 指示可以再次尝试时重试。


非常感谢。但是O_NONBLOCK是针对sockfd的,sockSend不应该是阻塞的(默认行为)吗?我使用sockfd接收数据,使用sockSend发送数据。我在fcntl()中删除了O_NONBLOCK,但是仍然出现相同的行为。这就是你所提到的,对吧? - Jary
通过删除 O_NONBLOCK 和 MSG_DONTWAIT,它最终可以正常工作!非常感谢!不过请问是否有办法保持一个套接字阻塞(发送),另一个不阻塞(用于接收)?! - Jary

0

如果您必须将套接字设置为非阻塞,则可以安全地(仅?)使用select

select()pselect()允许程序监视多个文件描述符,等待其中一个或多个文件描述符成为“就绪”以进行某些I/O操作的类别(例如,可能输入)。 如果可以执行相应的I/O操作(例如,read(2))而不会阻塞,则认为文件描述符已准备就绪。


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