fade2black fade2black - 6 months ago 23
Linux Question

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
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?

Answer

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.