我想创建一个非阻塞连接。 像这样:
socket.connect(); // returns immediately
为此,我使用另一个线程,一个无限循环和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
}
}
如果我运行服务器然后运行客户端,那么一切正常。如果我第一次运行客户端,请等待一小段时间,运行服务器,然后客户端无法连接。
我做错了什么?也许它可以以不同的方式完成?
答案 0 :(得分:35)
您应该使用以下步骤进行异步连接:
socket(..., SOCK_NONBLOCK, ...)
connect(fd, ...)
0
也不是EINPROGRESS
,则会中止错误fd
发出信号并准备输出getsockopt(fd, SOL_SOCKET, SO_ERROR, ...)
没有循环 - 除非你想处理EINTR
。
如果首先启动客户端,您应该在最后一步中看到错误ECONNREFUSED
。如果发生这种情况,请关闭套接字并从头开始。
如果没有看到更多细节,很难说清楚代码有什么问题。我想,您不会因check_socket
操作中的错误而中止。
答案 1 :(得分:1)
有几种方法可以测试无阻塞连接是否成功。
参考:UNIX网络编程V1
答案 2 :(得分:1)
D。 J. Bernstein聚集了各种方法来检查异步connect()
调用是否成功。这些方法中的许多方法在某些系统上确实具有缺点,因此为此编写可移植代码是很难的。如果有人想阅读所有可能的方法及其缺点,请check out this document。
对于那些只想要tl; dr版本的人,最可移植的方法如下:
系统一旦将套接字指示为可写状态,请首先调用getpeername()
以查看其是否连接。如果该调用成功,则套接字已连接,您可以开始使用它。如果该呼叫失败并显示ENOTCONN
,则连接失败。要找出失败的原因,请尝试从套接字read(fd, &ch, 1)
读取一个字节,该字节也将失败,但是您得到的错误是如果不是非connect()
,则会从c_id | Subject | Unit | Term
----------------------------------
1 | English | 3 | first
2 | Physics | 2 | first
3 | Maths | 3 | first
获得的错误-封锁。