6

I'm designing a C program in linux where I'll have two threads. One main thread is the event_processor_thread which does the main function processing. Second thread is an event_dispatcher thread running always in the background, writing to and reading from multiple interfaces in real time (non blocking async i/o)

I did some research on the net, and found that the best ways to implement non-blocking socket i/o can be accomplished via

  1. libevent
  2. select()

I chose the latter, as its easier, and i'll have at the most 4 interfaces to read from/write to.

I'm clear on the listen/read mechanisms using readfds, but I'm unsure on how to use the writefds! If I put my data from the event_processor_thread to a shared memory and have this event dispatcher thread read this from shared memory and write using send(), Will select take care of sending the data to socket on its own ? Is this why I need to use writefds in select()?

My apologies if my questions is not clear, what I basically want is to have a non blocking i/o thread to dispatch events to/from the event processor thread to the external interface. Any inputs in this regard is highly appreciated. Thanks!

Ztyx
  • 14,100
  • 15
  • 78
  • 114
vinit
  • 501
  • 5
  • 15
  • How would you implement a basic event-loop? http://stackoverflow.com/questions/658403/how-would-you-implement-a-basic-event-loop – HAL Nov 19 '13 at 13:02
  • Note that the libevent approach is more portable to different platforms. – Ztyx Jan 03 '16 at 08:26

3 Answers3

14

The writefds of select is to check that the file descriptor is ready for writing. For a socket that means that the send buffer associated with the socket is not full.

Let's assume that the sockets on your platform have an 8 kb buffer and you want to send 100 kb of data.

You call write and get a return value of 8192 indicating that the first 8192 bytes have been written. The next call to write returns either EAGAIN or EWOULDBLOCK indicating that the send buffer is full.

You can now use select to find out when there is room in send buffer again (that is, when one tcp/ip packet has been transferred to the client) so that you can continue writing. At the same time you can be listening for new connections and waiting for input from clients.

Note that select never sends any data, it just monitors the status of several file descriptors at once.

Klas Lindbäck
  • 33,105
  • 5
  • 57
  • 82
2

No, select() will not "take care of writing". It will notify you when one or more of the file descriptors included in the writefds set becomes writable. This can mean that the fd(s) in question have finished the previous (non-blocking) write you did, so that you can now do another.

unwind
  • 391,730
  • 64
  • 469
  • 606
  • Thanks unwind and @Klas Lindback, do you mean to say i should implement some thing like this: 1. write to socket 2. If num of bytes written is not full, return asap, 3. select() will send notification if socket is ready for write 4. write remaining data to socket – vinit Nov 19 '13 at 13:13
  • @vinit: Yes, that is one of the use cases for the `writefds` parameter of `select()` (though you don't stop when the number of bytes written is "not full", you stop when `send()`/`write()` tells you to stop because a `EAGAIN` or `EWOULDBLOCK` error occurs). Another use case is to detect when a non-blocking `connect()` is successful. – Remy Lebeau Nov 19 '13 at 22:16
2

select() tells you when a file descriptor is writable. For a socket, that means it can accept new outbound data without blocking the caller. If you call send() or write() and the socket's outbound buffer is full, you will get an EAGAIN or EWOULDBLOCK error, at which time you would stop writing to that socket until it becomes writable again. select() can also tell you when the socket becomes writable after a non-blocking connect() is called, indicating a successful connection has been made and data can start being written to the peer.

Remy Lebeau
  • 555,201
  • 31
  • 458
  • 770