Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How can I distinguish read and write events on the same socket?

Tags:

c

sockets

epoll

I'm using epoll to get notifications about incoming data. It's not hard because all events returned by epoll_wait() indicates, that I can read data from epoll_event.data.fd (socket descriptor).

But now I want get both types of notification: receiving and sending (socket is available for send). But I can't to do it because:

  1. epoll_event.events which is returned by epoll_wait() is the same as I pass in epoll_ctl(). So it contains both EPOLLIN and EPOLLOUT in my case.
  2. Also if i trying to twice add one socket in epoll (as EPOLLIN and as EPOLLOUT event) I'll get a EEXIST.

How can I solve this problem without manually calling select() every time I get notification?

like image 551
Nelson Tatius Avatar asked Oct 03 '12 16:10

Nelson Tatius


2 Answers

man epoll_wait clearly states that "the events member will contain the returned event bit field.". Therefore, if you are getting EPOLLIN | EPOLLOUT in epoll_event.events, then your socket must be ready for both reading and writing.

If you only want to be notified when the socket changes state, use EPOLLET for edge-triggered operation.

like image 128
nneonneo Avatar answered Nov 15 '22 00:11

nneonneo


When you add a descriptor using epoll_ctl, set the events mask to be EPOLLIN | EPOLLOUT.

When you get notifications via epoll_wait then you'd loop through the returned notifications checking for EPOLLIN and EPOLLOUT.

Pseudo code:

int index, count;
count = epoll_wait(epfd, epoll_event, MAX_EVENTS, -1);
for (index = 0; index < count; ++index) {
  if (epoll_event[index].events & EPOLLIN) {
    // Ready for read
  }

  if (epoll_event[index].events & EPOLLOUT) {
    // Ready for write
  }
}

Some people only set the EPOLLOUT bit when they have data present in their send buffer. I did not include any error checking.

like image 21
j.w.r Avatar answered Nov 14 '22 22:11

j.w.r