Linux,套接字,非阻塞连接
声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 
原文地址: http://stackoverflow.com/questions/17769964/
Warning: these are provided under cc-by-sa 4.0 license.  You are free to use/share it, But you must attribute it to the original authors (not me):
StackOverFlow
Linux, sockets, non-blocking connect
提问by herolover
I want to create a non-blocking connect. Like this:
我想创建一个非阻塞连接。像这样:
socket.connect(); // returns immediately
For this, I use another thread, an infinite loop and Linux epoll. Like this(pseudocode):
为此,我使用了另一个线程、一个无限循环和 Linux epoll。像这样(伪代码):
// in another thread
{
  create_non_block_socket();
  connect();
  epoll_create();
  epoll_ctl(); // subscribe socket to all events
  while (true)
  {
    epoll_wait(); // wait a small time(~100 ms)
    check_socket(); // check on EPOLLOUT event
  }
}
If I run a server and then a client, all it works. If I first run a client, wait a some small time, run a server, then the client doesn't connect.
如果我先运行服务器,然后运行客户端,则一切正常。如果我首先运行客户端,稍等片刻,运行服务器,则客户端无法连接。
What am I doing wrong? Maybe it can be done differently?
我究竟做错了什么?也许它可以以不同的方式完成?
采纳答案by nosid
You should use the following steps for an async connect:
您应该使用以下步骤进行异步连接:
- create socket with 
socket(..., SOCK_NONBLOCK, ...) - start connection with 
connect(fd, ...) - if return value is neither 
0norEINPROGRESS, then abort with error - wait until 
fdis signalled as ready for output - check status of socket with 
getsockopt(fd, SOL_SOCKET, SO_ERROR, ...) - done
 
- 创建套接字 
socket(..., SOCK_NONBLOCK, ...) - 开始连接 
connect(fd, ...) - 如果返回值既不是也不
0是EINPROGRESS,则中止错误 - 等待直到
fd发出信号准备好输出 - 检查套接字的状态 
getsockopt(fd, SOL_SOCKET, SO_ERROR, ...) - 完毕
 
No loops - unless you want to handle EINTR.
没有循环 - 除非你想处理EINTR.
If the client is started first, you should see the error ECONNREFUSEDin the last step. If this happens, close the socket and start from the beginning.
如果客户端首先启动,您应该会ECONNREFUSED在最后一步看到错误。如果发生这种情况,请关闭套接字并从头开始。
It is difficult to tell what's wrong with your code, without seeing more details. I suppose, that you do not abort on errors in your check_socketoperation.
如果不查看更多详细信息,很难判断您的代码有什么问题。我想,您不会因check_socket操作中的错误而中止。
回答by u861799
There are a few ways to test if a nonblocking connect succeeds.
有几种方法可以测试非阻塞连接是否成功。
- call getpeername() first, if it failed with error ENOTCONN, the connection failed. then call getsockopt with SO_ERROR to get the pending error on the socket
 - call read with a length of 0. if the read failed, the connection failed, and the errno for read indicates why the connection failed; read returns 0 if connection succeeds
 - call connect again; if the errno is EISCONN, the connection is already connected and the first connect succeeded.
 
- 首先调用 getpeername(),如果失败并出现错误 ENOTCONN,则连接失败。然后使用 SO_ERROR 调用 getsockopt 以获取套接字上的未决错误
 - 调用长度为0的read,如果读取失败,则连接失败,read的errno表示连接失败的原因;如果连接成功,则 read 返回 0
 - 再次调用connect;如果 errno 是 EISCONN,则连接已经连接并且第一次连接成功。
 
Ref: UNIX Network Programming V1
参考:UNIX 网络编程 V1

