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
0
norEINPROGRESS
, then abort with error - wait until
fd
is 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 ECONNREFUSED
in 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_socket
operation.
如果不查看更多详细信息,很难判断您的代码有什么问题。我想,您不会因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