我开始讨厌插座,请帮助。
所以我正在尝试连接到localhost网络中的某个位置。这可能在线也可能不在线。由于我想等待超过默认值的超时,我使用非阻塞connect
,+ select
。
struct sockaddr_in address;
address.sin_family = AF_INET;
address.sin_addr.s_addr = htonl(0x7f000001);
address.sin_port = htons(port);
const int timeout_int = 100; //in milliseconds
struct timeval timeout = { 0, timeout_int * 1000 };
SOCKET s = socket(AF_INET, SOCK_STREAM, IPPROTO_TCP);
#ifdef WIN32
u_long iMode = 1;
ioctlsocket(s, FIONBIO, &iMode);
#else
int socketFlags = fcntl( s, F_GETFL, 0 )
socketFlags |= O_NONBLOCK;
fcntl( s, F_SETFL, socketFlags )
#endif
connect(s, (struct sockaddr*) clientService, sizeof(struct sockaddr_in));
fd_set sock;
FD_ZERO(&sock);
FD_SET(s, &sock);
int result = select(s + 1, NULL, &sock, NULL, &timeout);
当然还有很多我错过的错误检查;但是不要担心,我正在做,而且一切似乎都处于完美的健康状态,除非它已经死了,可以这么说。
在Windows上它可以工作:它等待超时,如果找不到任何内容,它会将0返回result
,这正好意味着“超时”。
现在,有人建议我这样做
int soError;
socklen_t len = sizeof(soError);
getsockopt(s, SOL_SOCKET, SO_ERROR, (char*)&soError, &len);
然后,只有当soError
为0
时,连接才会成功。
但是为什么超时没有等待?我能相信Linux知道,如果我达到这一点,已经没有希望得到答案吗?
我已经尝试在剩余的超时时间内休眠,然后再次检查;但在这种情况下,我在所有情况下都得到soError == 0
,所以它不起作用。
或者我在其他方面做了一些完全错误的事情?
答案 0 :(得分:0)
并非所有连接错误都需要超时。例如,ECONNREFUSED导致立即失败。对于对等体根本没有响应的情况,超时就在这里。
答案 1 :(得分:0)
您应该检查连接返回码,仅当它返回ERROR并且errno是EWOULDBLOCK或EINPROGRESS(取决于OS)时,才调用select。可能是因为连接是在连接调用上建立的,因此选择调用返回了您已经可以写入该套接字的地址