首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >poll()是边缘触发函数吗?

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

Stack Overflow用户
提问于 2013-02-26 00:56:51
回答 3查看 1.8K关注 0票数 4

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

代码语言:javascript
复制
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()是一个级别触发函数,只要有数据要从套接字中读取,它就会立即解除阻塞。我所读到的一切似乎都支持这一假设。是否有我可能错过的原因导致上面的代码错过了一个读取事件?

EN

回答 3

Stack Overflow用户

回答已采纳

发布于 2013-02-26 01:08:11

它不是边缘触发的。它总是被电平触发。我将不得不阅读您的代码来回答您的实际问题。但这回答了标题中的问题。:-)

我在您的代码中看不到任何清晰的原因,为什么您可能会看到您看到的行为。但是您的问题的范围比您所呈现的代码大得多,我不能假装这是一个完整的问题诊断。

票数 5
EN

Stack Overflow用户

发布于 2013-02-26 09:02:25

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

票数 2
EN

Stack Overflow用户

发布于 2013-02-26 03:18:59

根据您自己对问题的评估(即,当您希望能够读取确认消息时,您在poll上被阻止),那么您最终将获得超时。

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

票数 1
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/15072165

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档