poll()是否预计需要40ms才能返回,即使数据会更快可用

Is it expected for poll() to take 40ms to return even though data will be available sooner?

本文关键字:数据 返回 是否 40ms poll      更新时间:2023-10-16

我创建了一个代理服务器来处理来自网站客户端的CQL订单。代理侦听传入的连接,每个连接都有一个线程。只要套接字存在,线程就会循环,并在HUP上终止。您也可以停止代理,它将通过向每个线程发送一个事件(请参阅eventfd())来停止线程。

就其本身而言,这已经让我节省了100毫秒的时间,因为代理是本地的,连接到本地服务比远程计算机上的服务快得多。。。(即使计算机是本地的。)

但是,我发送订单,代理偶尔看不到任何传入数据(即,它在设置为NONBLOCK的套接字上调用read(),并得到-1作为返回和errno == EAGAIN。)当这种情况发生时,我调用poll()以等待其他数据、HUPeventfd上的命中,这意味着我必须退出(即,2个fds、套接字和eventfd)。

不知何故,通常情况下,当我调用poll()函数时,它会使消息往返所需的时间增加40毫秒。虽然有人会认为这只会发生在较大的消息上,但当我收到小于100字节的订单时,就会发生这种情况!因此,尺寸不应该是罪魁祸首。我还更改了代码,以确保在一个write()中将整个订单从客户端发送到代理,并尽可能避免poll()(即,我首先调用read(),只有在没有可用的情况下才调用poll()

请注意,在这种情况下,我没有超时,因为除了传入订单和eventfd之外,没有什么可检查的。所以我想超时不会是个问题。

代码库真的很大。但是客户端/服务器可以归结为这样的东西(原始文件中的大小是完全动态的):

// Client
...
connect(socket);
...
write(socket, order, sizeof(order));
read(socket, result, sizeof(result));
// repeat for other orders, as required by client...

// server
...
socket = accept(); // happens for each client
...
pthread_create(runner);
...
// server thread (runner)
...
for(;;)
{
  int r(0);
  for(;;)
  {
    r += read(socket, order, sizeof(order));
    if(r >= sizeof(order))
    {
      break;
    }
    // wait for more data is not enough received yet
    poll(..."socket" + "eventfd"...);  // <-- this will often take 40ms
    if(eventfd_happened)
    {
      // quit thread
      return;
    }
  }
  ...
  [work on order]
  ...
  write(socket, result, sizeof(result));
}

注1:当我只有一个客户时,我会发现问题。因此,拥有多个客户端本身也不会造成问题。

注意2:客户端确实使用了[来自OpenSSL]的BIO_connect()、BIO_read()和BIO_write(),但我怀疑这会是个问题。我不使用任何类型的加密。

我不明白为什么要使用非阻塞I/O,因为每个套接字都有一个专用线程。只需在read()中阻塞。如果需要整体读取超时,请使用SO_RCVTIMEO