poll() 似乎没有看到 UDP 套接字上的事件

poll() doesn't seem to see events on an UDP socket

我正在尝试使用 poll() 编写网络程序。我在 struct pollfd 数组中创建一个 UDP,然后轮询它。但是,poll() returns 每次都是0,不管我给它发了多少次信息。当我只调用 recvfrom 时,它工作得很好。所以这是我的代码:

创建并绑定套接字:

struct pollfd[2] fds;
// ...
fds[0].fd = socket(AF_INET, SOCK_DGRAM, 0);
if (fds[0].fd < 0)
    syserr("socket");
listen_address = { 0 };
listen_address.sin_family = AF_INET;
listen_address.sin_addr.s_addr = htonl(INADDR_ANY); 
listen_address.sin_port = htons(m_port);
if (bind(
        fds[0].fd,
        (struct sockaddr*) &listen_address,
        (socklen_t) sizeof(listen_address)
        ) < 0)
    syserr("bind");

现在可以了:

for (;;) {
    memset(buffer, 0, BUF_SIZE + 1);
    rval = recvfrom(
        fds[0].fd,
        buffer,
        BUF_SIZE,
        0,
        (struct sockaddr *) &respond_address,
        &rcva_len
        );
    std::cout << buffer << std::endl;
}

但这不是

finished = false;
do {
    fds[0].revents = fds[1].revents = 0;
    ret = poll(fds, 2, 0);
    if (ret < 0) {
        perror("poll");
    } else if (ret == 0) {
        // the loop always enters here
    } else {
        // the loop never enters here,
        // even though I send messages to the socket
    }
} while (!finished);

为了测试,我使用这样的命令

echo -n “foo” | nc -4u -w1 <host> <udp port>

我希望能提供一些见解

您使用 poll() 的方式存在两个严重问题:

  1. 您必须为每个文件描述符设置revents字段,以指示您对哪些事件感兴趣,例如POLLIN and/or POLLOUT.您的代码无法将 revents 设置为任何内容。

  2. 第三个参数poll()是超时设置。您将其设置为 0。这意味着 "check the file descriptors for whether or not any of the requested events have occured, but always return immediately in any case, and if no file descriptors have the requested events then return 0".

您看到的是哪种行为。

为了等到任何文件描述符的事件发生,我不会告诉您需要将第三个参数设置为什么,我只会让您参考 poll() 的手册页。阅读手册页很好。他们解释一切。

总结:

  1. 正确初始化每个文件描述符的revents参数。

  2. 将正确的参数传递给 poll(),如其手册页所述。如果您希望 poll() 无限期地等待,直到任何传递的文件描述符的请求事件发生,可以使用特定的值来执行此操作。查一查。

  3. poll()returns之后,检查每个文件描述符的events参数以确定文件描述符的状态。