2011/6/20 Jaime Fernández <jjja...@gmail.com>:
> b) What's the most convenient way to write data in a TCP socket:
>     1.- "send" data directly in the read callback
>     2.- Create a write watcher
>     3.- Create a watcher of both types: READ&WRITE.

It really depends on the nature of the protocol and the data traffic's
patterns what will be the most efficient.  The most generic answer is
this: create both reader and writer watchers for the socket
separately, but only activate the read watcher when you need to
receive traffic, and only active the write watcher when you have
buffered data ready to write to the socket.  You can enable and
disable them independently with ev_io_start() and ev_io_stop().  e.g.
for a simple HTTP server, you might start with only the read watcher
enabled.  Once you've processed a request and have a response ready to
send, you turn on the write watcher to drain the buffered data, then
turn it off again when the write buffer is empty.

You can also write response data directly from the read watcher that
processed the request, and it will probably work 99% of the time for
most typical protocols with a serial conversation of reads and writes.
 However, the write could block because local buffers and the tcp
in-flight window are filled, at which point you'll need to buffer the
data somewhere per-connection and start up a write watcher to drain it
anyways.  One way or another, the implementation won't work 100%
unless you implement write watcher and a buffer somehow.

For an example of trying to be efficient and quick: I recently wrote a
proxy server that mostly passes clear data between two connections
(other than some initial protocol-specific setup traffic).  For that I
implemented both read and write watchers for both sides, so 4 watchers
per proxied connection.  You can think of them as read+write for each
socket, but it's more natural pair them the opposite way and think of
them as e.g. read_socket1+write_socket2 and
read_socket2+write_socket1, for each direction of traffic flow.

By default only the read watchers are turned on, and they attempt a
non-blocking optimistic write() to the other socket immediately at the
end of the read() callback.  If the write() fails due to blockage, the
data is buffered and the watchers are swapped: the read watcher is
disabled, the corresponding write watcher is enabled.  The
write-watcher, after each invocation where it drains part of the
buffer, attempts a non-blocking optimistic read() in order to try to
keep the buffer filled.  If the buffer drains completely, the traffic
flow switches back to watching for read() availability (stop the write
watcher, start the read watcher).

-- Brandon

_______________________________________________
libev mailing list
libev@lists.schmorp.de
http://lists.schmorp.de/cgi-bin/mailman/listinfo/libev

Reply via email to