是否有可能在接受事件上做epoll?

时间:2017-12-13 08:08:43

标签: c sockets posix epoll

我们假设我已经创建了一个侦听套接字:

sock = socket(...);
bind(sock,...);
listen(sock, ...);

是否可以在 sock 上执行epoll_wait以等待传入连接?那之后如何获得客户端套接字fd?

我正在为平台编写的东西不能是非阻塞的,但是有超时的工作epoll实现,我需要接受连接并在单个线程中使用它以便它不会如果出现问题并且没有连接,请挂起。

2 个答案:

答案 0 :(得分:0)

如果不知道这个非标准平台是什么,就不可能确切地知道他们给他们的epoll通话语义了什么。但是在Linux上的标准epoll上,监听套接字将报告为"可读"当传入连接到达时,您可以通过调用accept接受连接。如果您将套接字置于阻塞模式,并且在每次调用accept之前始终使用epoll的级别触发模式检查可读性,则此工作 - 唯一的风险是如果你在没有连接到达时以某种方式结束调用accept,那么你就会被卡住。例如,如果有两个进程共享侦听套接字,则会发生这种情况,并且它们都尝试accept相同的连接。或者,如果传入的连接到达,可能会发生,然后在您致电accept之前再次关闭。 (在这种情况下,Linux仍然可以让accept成功,但是这种边缘情况恰好是我对一个奇怪的平台做一些奇怪事情的怀疑。)你想要检查这些东西。

非阻止模式更加可靠,因为在最糟糕的情况下,accept只会报告无法接受。但是,如果没有,那么你可能会得到类似的东西......

答案 1 :(得分:0)

因为这个答案是鸭鸭结果中的第一个答案。我只是想说一下,在GNU / Linux 4.18.0-18-generic(Ubuntu 18.10)下。

使用一个异步accept传入连接必须注意errnoEWOULDBLOCK(11),然后将套接字添加到epoll read 集中。

以下是实现该目标的方案代码的一小部分:

(define (accept fd)
  (let ((out (socket:%accept fd 0 0)))
    (if (= out -1)
        (let ((code (socket:errno)))
          (if (= code EWOULDBLOCK)
              (begin
                (abort-to-prompt fd 'read)
                (accept fd))
              (error 'accept (socket:strerror code))))
        out)))

在上面的(abort-to-prompt fd 'read)中,将暂停协程并将fd添加到epoll读取集中,操作如下:

(epoll-ctl epoll EPOLL-CTL-ADD fd (make-epoll-event-in fd)))

当协程未暂停时,代码将在中止后继续以递归方式调用自身(在尾部调用位置)

在我使用Scheme编写的代码中,由于我依靠call/cc来避免回调,因此涉及的内容更多。完整代码位于source hut

仅此而已。