我编写了一个程序,使用非阻塞connect()
和select()
组合来检查到远程主机a的连接特定端口。select()
也有一些超时值,在我的情况下是2.5s。我正在测试该程序连接到在远程主机上运行SMTP服务的进程绑定到25号端口。如果我杀死在远程主机上运行的进程,那么select()
也会返回1来告诉该进程正在写(套接字添加到写入fd_set)是可能的。这背后的原因是什么,以及在这种情况下是否可以使用select()
。我尝试使用connect()
,当这种连接不可能时立即返回,但在连接需要超时的情况下不起作用,这就是为什么我使用select()
。
select()
并没有告诉你读写是可能的,它只是告诉你它不会阻塞(或者如果套接字处于非阻塞模式则返回错误EWOULDBLOCK
)。只要本地套接字缓冲区未满,套接字始终是可写的。此外,如果在远程进程死亡后发送了任何东西,您将收到一个RST包,并且在此之后尝试写将立即返回ECONNRESET
。因此,当这种情况发生时,套接字将被标记为可写。
我能够通过在select()
函数调用之后使用另一个connect()
来完成。张贴代码片段
error = connect(soc, (struct sockaddr *)serveraddr, sizeof(struct sockaddr)) ;
if(error == 0){
DIAGC("vsrserv", 1, "Returning while connect is 0");
return 0;
}
if(errno != EINPROGRESS)
return -1;
int retVal = select (soc+1, &writeFD, (fd_set *)NULL, (fd_set *)NULL, (struct timeval *)(&timeout));
if (retVal == 0){
close(soc);
return -1;
}
socklen_t len = 0;
int m = getsockopt(soc, SOL_SOCKET, SO_ERROR, &error, &len) ;
if(m < 0){
close(soc);
return -1;
}
//connect() returns immediately if it is able to connect to that particular port
//Since select() returned 1 it means host was reachable so just need to verify the port on the remote host which we can do with another with connect() call
error = connect(soc, (struct sockaddr *)serveraddr, sizeof(struct sockaddr)) ;
if(error < 0){
close(soc);
return -1;
}