【问题标题】:SO_REUSEADDR with UDP datagrams - Resource unavailable带有 UDP 数据报的 SO_REUSEADDR - 资源不可用
【发布时间】:2010-11-01 03:56:43
【问题描述】:

我正在使用 SO_REUSEADDR 选项,但我不确定为什么会得到 资源暂时不可用选项。

我正在 127.0.0.1 上测试客户端服务器代码

if ( (sockfd = socket(AF_INET, SOCK_DGRAM, 0)) < 0 )
{
    perror("socket() error!!\n");
    exit(1);
}

if ( setsockopt(sockfd, SOL_SOCKET, SO_REUSEADDR, &reuse, sizeof(reuse) ) < 0 ) {
    perror("SO_REUSEADDR failed::");
    exit(1);
}

while(1) {

    nbytes_read = recvfrom(sockfd, (void *)&recvd_msg, sizeof(recvd_msg),
                           flags, &from, &from_len);
    printf("nbytes_read = %d\n", nbytes_read);
    if(nbytes_read == -1) {
        perror("client: recvfrom() failed");
        return FAILED;
    }
    if (nbytes_read > 0) {
        if(recvd_msg.hdr.msgtype == DATA)
            printf("recvd %d bytes from server\n", recvd_msg.hdr.payload_size);
            ftp_show_payload(&recvd_msg);
    }
    if(recvd_msg.hdr.is_last == TRUE) {
        break;
    }
}

错误信息: “客户端:recvfrom() 失败:资源暂时不可用”

错误号:11

尝试运行客户端 3-4 次后,我得到了数据,我不确定发生了什么。

另外,这个问题出现在 Ubuntu Linux 上,但是当我在 Solaris 上运行相同的客户端服务器时, 它工作正常!

【问题讨论】:

  • 您不需要标签或 goto。使用继续。而且你只能在非阻塞模式下获得零,在这种情况下你应该选择(),而不仅仅是旋转。 'return'之后你不需要'else'。
  • 好的,我已经改变了你所说的一切,但我仍然不确定为什么我得到 EAGAIN(资源不可用)..
  • 不,你没有。如果你得到 EAGAIN,你必须处于非阻塞模式,所以你需要调用 select() 来告诉你数据何时可用。
  • 要处于非阻塞模式,我认为我们需要设置 O_NONBLOCK,但在我的代码中,我没有这样做
  • 好的,那么你删除了无意义的 SO_REUSEADDR 了吗?

标签: sockets unix udp


【解决方案1】:

SO_REUSEADDR 在您使用bind() 时很有用,但在这里您没有使用绑定。

如果recvfrom() 返回-1,我看不出有任何问题

使用bind() 并将您的电话recvfrom() 替换为recv()recv() 将在您在绑定调用中使用的端口接收所有数据包。

【讨论】:

    【解决方案2】:

    您是否正在删除任何其他套接字配置?当您读取非阻塞套接字并且没有可用数据时,通常会返回 EAGAIN。 recvfrom 的手册页列出了可能在失败时设置的 errno,并为每个错误提供了解释。

    【讨论】:

    • 我得到 errno:11 资源暂时不可用
    • 这是 EAGAIN(又名 EWOULDBLOCK)的“漂亮”名称。您可以通过打印出strerror(EAGAIN) 来验证这一点。可悲的是,我也知道 11 也是 EAGAIN ......
    • 但是为什么我会得到EAGAIN,我的udp文件服务器,给我发送了很多数据,有时我看到它,有时我看到EAGAIN,可能是什么原因
    • 数据不会像调用 recvfrom() 那样频繁。你需要选择()。往上看。否则就使用阻塞模式。
    【解决方案3】:
    1. 您的测试无效。 recvfrom() 可以返回零,这并不表示错误。只有当你得到 -1 时调用 perror() 才有效。所以你可能根本没有问题..

    2. 我不明白你为什么在这里使用 SO_REUSEADDR,因为你没有绑定到特定端口。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2012-09-14
      • 2011-01-09
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多