poll()是一个边缘触发函数吗?

我负责通过TCP连接导出数据的服务器。 对于服务器传输的每个数据logging,它都要求客户端发送一个简短的“\ n”确认消息。 我有一位客户声称他发送的确认不是从Web服务器读取的。 以下是我在套接字上用于I / O的代码:

bool can_send = true; char tx_buff[1024]; char rx_buff[1024]; struct pollfd poll_descriptor; int rcd; poll_descriptor.fd = socket_handle; poll_descriptor.events = POLLIN | POLLOUT; poll_descriptor.revents = 0; while(!should_quit && is_connected) { // if we know that data can be written, we need to do this before we poll the OS for // events. This will prevent the 100 msec latency that would otherwise occur fill_write_buffer(write_buffer); while(can_send && !should_quit && !write_buffer.empty()) { uint4 tx_len = write_buffer.copy(tx_buff, sizeof(tx_buff)); rcd = ::send( socket_handle, tx_buff, tx_len, 0); if(rcd == -1 && errno != EINTR) throw SocketException("socket write failure"); write_buffer.pop(rcd); if(rcd > 0) on_low_level_write(tx_buff, rcd); if(rcd < tx_len) can_send = false; } // we will use poll for up to 100 msec to determine whether the socket can be read or // written if(!can_send) poll_descriptor.events = POLLIN | POLLOUT; else poll_descriptor.events = POLLIN; poll(&poll_descriptor, 1, 100); // check to see if an error has occurred if((poll_descriptor.revents & POLLERR) != 0 || (poll_descriptor.revents & POLLHUP) != 0 || (poll_descriptor.revents & POLLNVAL) != 0) throw SocketException("socket hung up or socket error"); // check to see if anything can be written if((poll_descriptor.revents & POLLOUT) != 0) can_send = true; // check to see if anything can be read if((poll_descriptor.revents & POLLIN) != 0) { ssize_t bytes_read; ssize_t total_bytes_read = 0; int bytes_remaining = 0; do { bytes_read = ::recv( socket_handle, rx_buff, sizeof(rx_buff), 0); if(bytes_read > 0) { total_bytes_read += bytes_read; on_low_level_read(rx_buff,bytes_read); } else if(bytes_read == -1) throw SocketException("read failure"); ioctl( socket_handle, FIONREAD, &bytes_remaining); } while(bytes_remaining != 0); // recv() will return 0 if the socket has been closed if(total_bytes_read > 0) read_event::cpost(this); else { is_connected = false; closed_event::cpost(this); } } } 

我已经写了这个代码的基础上,假设poll()是一个级别触发函数,只要有数据从套接字读取将立即unblock。 我所读的一切似乎都支持这个假设。 是否有一个原因,我可能错过了会导致上述代码错过一个阅读事件?

这不是边缘触发。 它始终是电平触发的。 我将不得不阅读你的代码来回答你的实际问题。 但是,这在标题中回答了这个问题。 🙂

在你的代码中,我可以看到没有明确的理由,为什么你可能会看到你所看到的行为。 但是你的问题的范围比你提出的代码大很多,我不能假装这是一个完整的问题诊断。

根据你自己对问题的评估(也就是说,当你期望能够阅读确认时,你被阻止了poll ),那么你最终会得到一个超时。

如果客户的机器离您的服务器超过50毫秒,那么在您收到确认消息之前,您将始终在连接上超时,因为您只需等待100毫秒。 这是因为数据到达客户需要至少50ms,确认返回至少需要50ms。

它是电平触发的。 轮询时,如果套接字接收缓冲区中有数据,则POLLIN触发,如果套接字发送缓冲区中有空间(几乎总是存在),则触发POLLOUT。