views:

384

answers:

3

I have an application that is going to work like a p2p-software where all peer are going to talk to each other. Since the communication will be TCP i thought that I could use epool(4) so that multiple connections can be handled. Since each peer will send data very often, I thought that I will establish a persistent connection to each peer that will be used under the applications lifetime.

Now, one thing that I don't know how to handle is that since the connection is never closed how do I know when i should stop receiving data with read() and call epool_wait() again to listen after more packages? Or is there a better way of dealing with persistent TCP connections?

A: 

read() reads as much data as is immediately available (but no more that you request). Just run read() on the active socket, with a big-enough buffer (you probably don't need it bigger than your MTU… 2048 bytes will do) and call epoll_wait() when it completes.

Jacek Konieczny
A: 

That should have been 'epoll', not 'epool'...not familiar with epoll, but have a look here at the Beej's guide to see an example of the sockets using 'poll'...look at section 7.2 in there to see how it is done, also look at the section 9.17 for the usage of 'poll'...

Hope this helps, Best regards, Tom.

tommieb75
Yea, that was a typo from me :) Thanks for the link.
DeeD
+1  A: 

You should set the socket to non-blocking, and when epoll indicates there is data to read you should call read() in a loop until read() returns -1 and errno is EWOULDBLOCK

That is, your read loop could look sometihng like:

for(;;)
  ssize_t ret;
  ret = read(...);
  if(ret == 0) {
     //client disconnected, handle it, remove the fd from the epoll set
      break;
  } else if(ret == -1) {
     if(errno == EWOULDBLOCK) {
        // no more data, return to epoll loop
      } else {
        //error occured, handle it remove the fd from the epoll set
      }
      break;
  }

 // handle the read data 
}

If you're not using edge triggered mode with epoll, you don't really need the loop - you could get away with doing just 1 read and return to the epoll loop. But handle the return values just like the above code.

nos
Alternatively, you can use `recv` instead of `read`, and supply the `MSG_DONTWAIT` flag. Don't forget your `SIGPIPE` handling, too.
caf