Async connects and disconnects from epoll (Linux)

I need asynchronous connection and disconnection for tcp client using epoll for Linux. There is ext. functions in Windows, such as ConnectEx, DisconnectEx, AcceptEx, etc. .... In the tcp server, the standard accept function works, but the connection does not work in the tcp client and disconnects ... All sockets are not blocked.

How can i do this?

Thanks!

+8
linux asynchronous sockets tcp epoll
source share
4 answers

To make a non-blocking connection () if the socket has already been non-blocked:

int res = connect(fd, ...); if (res < 0 && errno != EINPROGRESS) { // error, fail somehow, close socket return; } if (res == 0) { // connection has succeeded immediately } else { // connection attempt is in progress } 

In the second case, when connect () failed with EINPROGRESS (and only in this case), you need to wait until the socket is writable, for example. for epoll, indicate that you expect EPOLLOUT on this socket. After you receive a notification that it is writable (with epoll, also expect to receive an EPOLLERR or EPOLLHUP event), check the result of the connection attempt:

 int result; socklen_t result_len = sizeof(result); if (getsockopt(fd, SOL_SOCKET, SO_ERROR, &result, &result_len) < 0) { // error, fail somehow, close socket return; } if (result != 0) { // connection failed; error code is in 'result' return; } // socket is ready for read()/write() 

In my experience, on Linux, connect () never succeeds, and you always need to wait for write capabilities. However, for example, on FreeBSD, I saw a non-blocking connection () to the local host right after that.

+29
source share

From experience, when a non-blocking compound is detected, epoll is slightly different from select and poll.

with epoll:

After calling connect (), check the return code.

If the connection cannot be made immediately, register an EPOLLOUT event with epoll.

Call epoll_wait ().

If the connection failed, your events will be populated using EPOLLERR or EPOLLHUP, otherwise EPOLLOUT will be activated.

+2
source share

I tried Sonny's solution and epoll_ctl will return an invalid argument. Therefore, I think that maybe the right way to do this is:

1.create socketfd and epollfd

2.use epoll_ctl to bind socketfd and epollfd to the epoll event.

3.do connect (socketfd, ...)

4.check return value or errno

5.if errno == EINPROGRESS, do epoll_wait

+1
source share

I have a "full" answer here if someone else is looking for this:

 #include <sys/epoll.h> #include <errno.h> .... .... int retVal = -1; socklen_t retValLen = sizeof (retVal); int status = connect(socketFD, ...); if (status == 0) { // OK -- socket is ready for IO } else if (errno == EINPROGRESS) { struct epoll_event newPeerConnectionEvent; int epollFD = -1; struct epoll_event processableEvents; unsigned int numEvents = -1; if ((epollFD = epoll_create (1)) == -1) { printf ("Could not create the epoll FD list. Aborting!"); exit (2); } newPeerConnectionEvent.data.fd = socketFD; newPeerConnectionEvent.events = EPOLLOUT | EPOLLIN | EPOLLERR; if (epoll_ctl (epollFD, EPOLL_CTL_ADD, socketFD, &newPeerConnectionEvent) == -1) { printf ("Could not add the socket FD to the epoll FD list. Aborting!"); exit (2); } numEvents = epoll_wait (epollFD, &processableEvents, 1, -1); if (numEvents < 0) { printf ("Serious error in epoll setup: epoll_wait () returned < 0 status!"); exit (2); } if (getsockopt (socketFD, SOL_SOCKET, SO_ERROR, &retVal, &retValLen) < 0) { // ERROR, fail somehow, close socket } if (retVal != 0) { // ERROR: connect did not "go through" } } else { // ERROR: connect did not "go through" for other non-recoverable reasons. switch (errno) { ... } } 
0
source share

All Articles