套接字能否在 EWOULDBLOCK 之后但在 epoll_wait 之前变得可写?

Can a socket become writeable after an EWOULDBLOCK but before an epoll_wait?

我有一个基于反应器的设计,其中在 epoll_wait.

中轮询多个套接字文件描述符

为了优化延迟而非吞吐量,在写入套接字时,我们尝试立即直接写入文件描述符。

EWOULDBLOCK的情况下,我们缓冲未写入的数据,然后等待套接字再次变为可写。

下次我们的 epoll_wait returns 我们的文件描述符为可写时,我们然后从缓冲数据发送。

问题是,在之后我们收到一个EWOULDBLOCK但在之前我们调用epoll_wait?

也就是说,如果我们进行 2 次 write 调用,其中第一个 write 被部分写入其余部分缓冲,然后执行第二个 write,尝试立即写入,套接字是否可以在第一次和第二次写入调用之间变得可写,我们最终得到-在远端接收订单数据?

Can a socket become writeable after an EWOULDBLOCK but before an epoll_wait?

是的。当套接字发送缓冲区中存在 space 时,它可以变得可写,一旦其中现有数据的任何前缀被对等方确认,与您的应用程序异步,就会发生这种情况。

In order to optimise for latency not throughput, when writing to a socket we attempt to write directly to the file descriptor immediately.

很好。

In the event of EWOULDBLOCK we then buffer the unwritten data and then wait for the socket to become writeable again. The next time our epoll_wait returns our file descriptor as writeable, we then send from the buffered data.

再次VG。

The question is, can the socket become writeable after we receive an EWOULDBLOCK but before we call epoll_wait?

是的,见上文。

That is, if we do 2 write calls, where the first write is partially written and the remainder buffered, and then do the second write, attempting to write immediately, could the socket become writeable between the first and second write call

是的,见上文。

and we end up with out-of-order data being received on the far side?

我不知道怎么做,除非你从多个线程写入套接字。

The question is, can the socket become writeable after we receive an EWOULDBLOCK but before we call epoll_wait?

是的,可以。在 EWOULDBLOCK 时,套接字缓冲区已满。但是一旦对等方确认一些数据并且 space 在套接字缓冲区中清除,套接字就会再次变得可写。这发生在代码之外的后台,因此套接字可以在 任何 时间变得可写。

That is, if we do 2 write calls, where the first write is partially written and the remainder buffered, and then do the second write, attempting to write immediately, could the socket become writeable between the first and second write call, and we end up with out-of-order data being received on the far side?

是的,可以。这将是您的代码逻辑中的错误,因为您试图在完成写入任何 缓冲数据 之前将 new data 写入套接字还在等待发送。

当您检测到 EWOULDBLOCK 并开始缓冲数据时,停止 为任何新数据调用 write(),直到您的缓冲区被完全清除。如果您需要发送新数据,并且缓冲区中已经有数据,只需将新数据附加到缓冲区的末尾并继续,甚至根本不要调用 write()。每当套接字报告为可写时,请检查您的缓冲区中是否有任何待处理数据,如果有,则从缓冲区的前面尽可能多地发送,同时删除成功发送的数据,直到缓冲区被清除或EWOULDBLOCK又被举报了