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

C++ poll()不';似乎看不到UDP套接字上的事件,c++,sockets,udp,C++,Sockets,Udp,我正在尝试使用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_

我正在尝试使用
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");
struct pollfd[2]fds;
// ...
fds[0].fd=socket(AF_INET,SOCK_DGRAM,0);
if(fds[0].fd<0)
系统错误(“套接字”);
侦听地址={0};
listen\u address.sin\u family=AF\u INET;
侦听地址sin地址s地址=htonl(INADDR\U ANY);
listen_address.sin_port=htons(m_port);
如果(绑定)(
fds[0].fd,
(结构sockaddr*)和侦听地址,
(socklen_t)sizeof(侦听地址)
) < 0)
系统错误(“绑定”);
现在,这项工作:

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;
}
(;;)的
{
memset(缓冲区,0,BUF_大小+1);
rval=recvfrom(
fds[0].fd,
缓冲器
大小,
0,
(结构sockaddr*)和响应地址,
&rcva_len
);

std::cout使用poll()的方式有两个关键问题:

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

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

  • 这就是你看到的行为

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

    总之:

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

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

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


  • 使用
    poll()
    的方式有两个关键问题:

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

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

  • 这就是你看到的行为

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

    总之:

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

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

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


  • 不要SMAP标签。这是C++,不是C,而且,不是,库源代码的语言没有关系!不要SMAP标签。这是C++,不是C。而且,不,库源代码的语言也没关系!谢谢,我从来没有觉得太舒服了。
    ,但我几乎不知道这意味着什么,直到你在这里解释好了,你真的需要弄清楚如何更“舒适”阅读手册页。学习如何阅读和理解技术规范是一项强制性的技能,不仅仅是对每一个C++开发者,而是对任何语言或IT技能的开发者。只是一个建议。现在这是一个很好的机会:打开民意调查手册页,开始阅读,不要停下来,直到你理解它的每一个字。最后再看几遍。这可能会花你几个小时,但时间会花得很好。不仅仅是通过学习poll(),而是通过学习如何阅读手册页。当然你是对的,我实际上指的是linux手册页,它碰巧是以一种非常具体的方式编写的。那么我最好开始我的家庭作业。谢谢你的建议“revents”和“events”是交换的。“events”是一个输入,“revents”是一个输出Hanks很多,我从来没有对手册页感到太舒服过。它提到
    短事件输入事件标志(见下文)
    ,但在你解释之前我几乎不知道这意味着什么。好吧,你真的需要弄清楚如何更“舒服”阅读手册页。学习如何阅读和理解技术规范不仅是每一个C++开发者的必备技能,也是任何语言或IT技能的开发者的一个必备技能。只是一个建议。这对你来说是个好机会:打开民意调查手册页,开始阅读,不要停下来,直到你明白为止。
    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>