asynchronous连接和断开与epoll(Linux)

我需要asynchronous连接和断开使用epolltcp客户端为Linux。 有分机。 在Windows中的函数,如ConnectEx,DisconnectEx,AcceptEx等…在tcp服务器标准接受函数正在工作,但在TCP客户端不工作连接和断开…所有套接字都是非阻塞的。

我怎样才能做到这一点?

谢谢!

要做一个非阻塞连接(),假设套接字已经被非阻塞:

 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 } 

对于第二种情况,connect()在EINPROGRESS失败的情况下(只有在这种情况下),你必须等待套接字是可写的,例如epoll指定你正在等待这个套接字上的EPOLLOUT。 一旦得到通知它是可写的(使用epoll, 期望得到EPOLLERR或EPOLLHUP事件),请检查连接尝试的结果:

 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() 

根据我的经验,在Linux上,connect()永远不会立即成功,而且您总是需要等待可写。 但是,例如,在FreeBSD上,我已经看到了非阻塞connect()到localhost的成功。

从经验来看,当检测到非阻塞连接时,epoll与select和poll有点不同。

与epoll:

connect()调用完成后,检查返回码。

如果连接不能立即完成,则使用epoll注册EPOLLOUT事件。

调用epoll_wait()。

如果连接失败,你的事件将被填充EPOLLERR或EPOLLHUP,否则EPOLLOUT将被触发。

我有一个“完整的”答案,以防其他人正在寻找这个:

 #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) { ... } } 

我已经尝试了Sonny的解决方案,epoll_ctl将返回无效的参数。 所以我想也许正确的做法如下:

1.创建socketfd和epollfd

2.使用epoll_ctl将socketfd和epollfd与epoll事件相关联。

3.do connect(socketfd,…)

4.检查返回值或errno

5.如果errno == EINPROGRESS,请执行epoll_wait