Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How can I buffer non-blocking IO?

When I need buffered IO on blocking file descriptor I use stdio. But if I turn file descriptor into non-blocking mode according to manual stdio buffering is unusable. After some research I see that BIO can be usable for buffering non-blocking IO.

But may be there are other alternatives?

I need this to avoid using threads in a multi-connection environment.

like image 501
vitaly.v.ch Avatar asked Dec 01 '22 08:12

vitaly.v.ch


2 Answers

I think what you are talking about is the Reactor Pattern. This is a pretty standard way of processing lots of network connections without threads, and is very common in multiplayer game server engines. Another implementation (in python) is twisted matrix.

The basic algorith is:

  • have a buffer for each socket
  • check which sockets are ready to read (select(), poll(), or just iterate)
  • for each socket:
    • call recv() and accumulate the contents into the socket's buffer until recv returns 0 or an error with EWOULDBLOCK
    • call application level data handler for the socket with the contents of the buffer
    • clear the socket's buffer
like image 142
sean riley Avatar answered Dec 04 '22 07:12

sean riley


I see the question has been edited now, and is at least more understandable than before.

Anyway, isn't this a contradiction?

  • You make I/O non-blocking because you want to be able to read small amounts quickly, typically sacrificing throughput for latency.
  • You make it buffered because you don't care that much about latency, but want to make efficient use of the I/O subsystem by trading latency for throughput.

Doing them both at the same time seems like a contradiction, and is hard to imagine.

What are the semantics you're after? If you do this:

int     fd;
char    buf[1024];
ssize_t got;

fd = setup_non_blocking_io(...);
got = read(fd, buf, sizeof buf);

What behavior do you expect if there is 3 bytes available? Blocking/buffered I/O might block until able to read more satisfy your request, non-blocking I/O would return the 3 available bytes immediately.

Of course, if you have some protocol on top, that defines some kind of message structure so that you can know that "this I/O is incomplete, I can't parse it until I have more data", you can buffer it yourself at that level, and not pass data on upwards until a full message has been received.

like image 31
unwind Avatar answered Dec 04 '22 07:12

unwind