非阻塞套接字连接后select返回1

3
首先,我想说这个问题与这个不同:类似但不相同 我的代码长这样:
struct addrinfo hints, *res;
struct sockaddr* serveraddr;

memset(&hints, 0, sizeof(hints));
hints.ai_family = AF_INET;
hints.ai_socktype = SOCK_STREAM;

int res2 = getaddrinfo(ip, port, &hints, &res);
printf("getaddrinfo() res: %d, %d\n", res2, errno);

serveraddr = res->ai_addr;

//create new socket

int soc = socket(AF_INET, SOCK_STREAM, IPPROTO_TCP);
printf("socket() res: %d, %d\n", socket, errno);

//set nonblocking mode
unsigned long on = 1;
res2 = ioctl(soc, FIONBIO, &on);
printf("ioctl() res: %d\n, %d", res2, errno);

res2 = connect(soc, serveraddr, sizeof(struct sockaddr));
printf("connect() res: %d, %d\n", res2, errno);

//check if socket is ready
fd_set wfds;
FD_ZERO(&wfds);
FD_SET(soc, &wfds);

struct timeval t;
t.tv_sec=15;
t.tv_usec=0;

res2 = select(soc + 1, 0, &wfds, 0, &t);
printf("select() res: %d, %d\n", res2, errno);`

我正在连接一台存在的机器(IP地址存在,但没有服务器在监听我尝试连接的端口)。

选择操作(select)始终返回1。为什么?根据手册,它应该超时并返回0。 之后,当我尝试向套接字(socket)写入数据时,它返回-1/ECONNREFUSED。

这是预期行为吗?如果是,那么如何在select()之后检查我们是否已连接?


预期的结果是吗?是的。如何检查?请访问http://cr.yp.to/docs/connect.html。 - pilcrow
2个回答

8

我不知道你在man手册的哪里看到应该超时。

如果没有防火墙丢弃数据包,连接将很快被拒绝(来自您的主机的一个数据包,一个回复数据包)。因此,一旦收到重置信号,连接套接字上的“事件”就会到来。这将唤醒select,并激活至少一个套接字。

首次尝试从该套接字读取或写入将返回底层连接错误。


问题得到了很好的回答。 - Santhosh Pai

2
这是正确的行为,因为待处理的错误会导致套接字同时变得可读和可写。与任何其他系统调用一样,您需要显式地检查错误条件。您可以将套接字包含在异常fdset(select()的第四个参数)中,并直接获取通知,或者稍后以多种方式检查错误。
写入套接字时要小心,可能会发生SIGPIPE。通常,您应该设置一个SIGPIPE处理程序并同步处理EPIPE错误。

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接