【发布时间】:2018-06-21 16:55:27
【问题描述】:
使用alarm() 是唯一在unix 域套接字上设置connect() 超时的吗?我已经尝试过 select() ,它被描述为here 但似乎 select() 每次都会在 unix 域套接字上立即返回 ok 并且
调用getsockopt(SO_ERROR) 没有发生错误,但是fd 上的send() 返回错误Transport endpoint is not connected。我在下面粘贴 select() 代码。
我认为使用警报会满足这种情况,但似乎它被认为是一种老式的方式。所以我来这里看看是否有其他解决方案。提前致谢。
if ((flags = fcntl(fd, F_GETFL, 0)) == -1) {
syslog(LOG_USER|LOG_ERR, "fcntl get failed: %s", strerror(errno));
close(fd);
return -1;
}
if (fcntl(fd, F_SETFL, flags | O_NONBLOCK) == -1) {
syslog(LOG_USER|LOG_ERR, "set fd nonblocking failed: %s", strerror(errno));
close(fd);
return -1;
}
if(connect(fd, (struct sockaddr *) &address, sizeof(struct sockaddr_un)) != 0) {
if (errno != EAGAIN && errno != EWOULDBLOCK && errno != EINPROGRESS) {
close(fd);
return -1;
}
FD_ZERO(&set);
FD_SET(fd, &set);
if(select(fd + 1, NULL, &set, NULL, &timeout) <= 0) {
close(fd);
return -1;
}
/*
if(connect(fd, (struct sockaddr *) &address, sizeof(struct sockaddr_un)) != 0) {
close(fd);
return -1;
}
*/
if (getsockopt(fd, SOL_SOCKET, SO_ERROR, &error, (socklen_t *)&len) < 0) {
syslog(LOG_USER|LOG_ERR, "getsockopt failed: %s", strerror(errno));
close(fd);
return -1;
}
if(error != 0) {
syslog(LOG_USER|LOG_ERR, "getsockopt return error: %d", error);
close(fd);
return -1;
}
}
if (fcntl(fd, F_SETFL, flags & ~O_NONBLOCK) == -1) {
syslog(LOG_USER|LOG_ERR, "set fd blocking failed: %s", strerror(errno));
close(fd);
return -1;
}
【问题讨论】:
-
connect() 在 unix 域套接字上将立即完成或失败。但是,如果您愿意,您可以使用 select(),就像使用 select 在 TCP 套接字上执行非阻塞 connect() 一样。如果 select 立即返回 0,您可能做错了什么。
-
@nos 但是我做了一个测试,我通过发送信号 SIGSTOP 暂停域套接字的服务器端,然后用 strace 一次又一次地运行客户端可执行文件,几次后,strace 显示客户端挂在 connect() 系统调用上。
-
你的文件描述符设置为非阻塞模式了吗?
-
@nos 不,因为我想要超时。如果我将 fd 设置为非阻塞,它根本不会等待。
-
@nos 我已经编辑了我的线程以粘贴我的 select() 代码。代码运行良好,select()返回码ok(大于零),但是send()会返回错误Transport endpoint is not connected