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

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

本文关键字:套接字 事件 UDP 看不到 poll      更新时间:2023-10-16

我正在尝试使用poll()编写一个web程序。我在struct pollfd数组中创建一个UDP,然后轮询它。但是,无论我向它发送多少次消息,poll()每次都返回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和/或POLLOUT。您的代码无法将revents设置为任何值。

  2. poll()的第三个参数是超时设置。您正在将其设置为0。这意味着"检查文件描述符是否发生了任何请求的events,但在任何情况下都会立即返回,如果没有文件描述符包含请求的事件,则返回0"。

这就是你所看到的行为。

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

结论:

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

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

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