Reputation: 19780
With epoll after I accept a connection socket that's set to listen for EPOLLIN
events, and I get an EPOLLIN
event, do I have to read all of the data (until 0
) before I epoll_ctl
to only EPOLLOUT
?
Example: I have an HTTP server using epoll and I only want to read (EPOLLIN
with recv
) the HTTP headers until \r\n\r\n
. Can I safely ignore the rest of the message without reading it and switch to output (EPOLLOUT
with send
)?
Upvotes: 1
Views: 4564
Reputation: 104589
Short answer is yes, it's safe. A few things.
The alternative of "read all the data until 0" is actually not going to work anyway. A browser client won't shutdown/close its end of the socket until after it consumes the response back from the server. So you'd stall waiting for recv to return 0 because the remote client is still waiting for you to respond.
Assuming you are not using edge-triggered mode, you should be fine without having to worry about missing any notifications. You can consume just the header with EPOLLIN notifications and recv(), then epoll_ctl the socket to just receive EPOLLOUT notifications. When you are done sending the response, the safe thing to do is switch back to listening to EPOLLIN notifications (and possibly EPOLLHUP and EPOLLRDHUP) to consume any extra data in the request until the client closes his socket (in which case recv will return 0).
Edge triggered mode can be used too. Just make sure to use non-blocking sockets and attempt a non-blocking send when switching to response mode even if you didn't get an initial EPOLLOUT. When switching back to reading mode, do a non-blocking recv in case you lost an earlier EPOLLIN.
It's somewhat possible if a dumb client is attempting to send more than just the header (like a long set of POST data bytes), the client may not be attempting to recv a response until after it has finished sending. As such you get into a virtual deadlock. Both server and client can't write additional bytes to their sockets because neither side is reading. Simple solution is to make sure you consume the entire request (header and "Content-Length" bytes) before sending a response.
Upvotes: 1