Search code examples
clinuxsocketsepoll

Level-triggered or edge-triggered?


I have a server application that listens to a port, accepts (TCP) peer connections, and then for each socket it

1) reads (no more than 30 bytes of data)

2) sends (1 byte ack)

3) reads (no more than 2K)

4) sends (1 byte ack)

5) closes (connection)

I use epoll loop in my application. I want epoll_wait to return (with event list with EPOLLIN flags) only when all data arrived from a peer, so that I could read with a single read/recv call into array. If all data has not been received on a certain socket fd I don't want epoll to add this fd to the event list.

As far as I understand differences between level-triggered and edge-triggered modes of epoll this behavior can be reached using edge-triggered epoll with nonblocking sockets plus finite states to keep track of steps.

Please correct me if I am wrong with the edge-triggered option. Any idea?


Solution

  • It does not seem to be possible to set the minimum number of bytes available in the incoming socket buffer before epoll_wait reports the socket ready for read.

    man socket(7):

    SO_RCVLOWAT and SO_SNDLOWAT

    Specify the minimum number of bytes in the buffer until the socket layer will pass the data to the protocol (SO_SNDLOWAT) or the user on receiving (SO_RCVLOWAT). These two values are initialized to 1. SO_SNDLOWAT is not changeable on Linux (setsockopt(2) fails with the error ENOPROTOOPT). SO_RCVLOWAT is changeable only since Linux 2.4. The select(2) and poll(2) system calls currently do not respect the SO_RCVLOWAT setting on Linux, and mark a socket readable when even a single byte of data is available. A subsequent read from the socket will block until SO_RCVLOWAT bytes are available.

    Unless the man page is out of date.