int tcp_sock = ::socket(PF_INET, SOCK_STREAM, IPPROTO_TCP);
struct sockaddr_in remoteaddr;
struct sockaddr_in localAddr;
short local_port = 22222;
short remote_port = 33333;
// local addr
localAddr.sin_family = AF_INET;
localAddr.sin_port = htons(local_port);
localAddr.sin_addr.s_addr = 0xC0A80AA5; // we don't give a shit
int addrLen = sizeof(struct sockaddr_in);
//Now bind TCP to local addr
int result = bind(tcp_sock,(struct sockaddr*)&localAddr,addrLen);
if (result < 0)
{
perror("\nbind failed");
close(tcp_sock);
return -1;
}
result = connect(tcp_sock, (struct sockaddr*)&remoteaddr, sizeof(struct sockaddr_in));
printf("\nConnect returned %d, error no: %d", result, errno);
此处connect()
呼叫在很长一段时间后失败。在我选择的时间后,有什么方法可以使connect
函数返回?我尝试从另一个线程调用close()
,但这不会改变任何内容。
答案 0 :(得分:3)
在调用connect()
之前将套接字置于非阻塞模式,然后您可以使用select()
指定超时。 select()
将告诉您连接是成功还是超时。如果成功,您可以根据需要将套接字重新置于阻止模式。如果失败/超时,请关闭套接字。
int tcp_sock = ::socket(PF_INET, SOCK_STREAM, IPPROTO_TCP);
...
int flags = fcntl(tcp_sock, F_GETFL, 0);
fcntl(tcp_sock, F_SETFL, flags | O_NONBLOCK);
result = connect(tcp_sock, ...);
if (result == -1)
{
if (errno == EINPROGRESS)
{
fd_set wfd;
FD_ZERO(&wfd);
FD_SET(tcp_sock, &wfd);
struct timeval timeout;
timeout.tv_sec = ...;
timeout.tv_usec = ...;
result = select(tcp_sock+1, NULL, &wrd, NULL, &timeout);
if (result > 0)
{
// connected
fcntl(tcp_sock, F_SETFL, flags);
}
else if (result == 0)
{
// time out
}
else
{
// error
}
}
}
答案 1 :(得分:1)
如果花费时间,那么摆脱连接的唯一方法就是使套接字无阻塞。如果它是一个阻塞套接字,你就无法离开。
在我选择的时间后,有什么方法可以让连接函数返回?
您的选择是将套接字标记为非阻塞。别无他法。阻塞意味着“阻塞”执行线程,直到套接字上发生事件为止。您不能根据需要使用阻塞套接字和超时。
使用select
或epoll
机制来监控套接字。
答案 2 :(得分:1)
在我选择的时间后,有什么方法可以让连接函数返回?
向该过程发送信号。
#define TIME_OUT_SECONDS (15)
void alarm_handler(int sig)
{
/* Do nothing. */
}
int main(void)
{
...
signal(alarm_handler);
alarm(TIME_OUT_SECONDS);
result = connect(tcp_sock, ...);
...