如何摆脱 TCP 阻塞 connect() 调用?
How to get out from a TCP blocking connect() call?
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
在我选择的时间后发挥 return 的作用吗?我尝试从另一个线程调用 close()
但这并没有改变任何东西。
在调用connect()
之前将套接字设置为非阻塞模式,然后可以使用select()
指定超时。 select()
会告诉你连接成功还是超时。如果成功,您可以根据需要将套接字重新置于阻塞模式。如果 failed/timeout,则关闭套接字。
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);
int errCode = 0;
result = connect(tcp_sock, ...);
if (result < 0)
{
errCode = errno;
if (errCode == 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, &wfd, NULL, &timeout);
if (result > 0)
{
socklen_t len = sizeof(errCode);
result = getsockopt(tcp_sock, SOL_SOCKET, SO_ERROR, &errCode, &len);
if (result < 0)
errCode = errno;
else
result = (errCode == 0) ? 0 : -1;
}
else if (result == 0)
{
errCode = ETIMEDOUT;
result = -1;
}
else
{
errCode = errno;
}
}
}
if (result == 0)
{
// connected
fcntl(tcp_sock, F_SETFL, flags);
...
}
else
{
// error, use errCode as needed
...
}
如果花费时间,唯一摆脱连接的方法是使套接字成为非阻塞的。如果是阻塞套接字,你就出不去了。
Is there any way that I can make connect function return after a time of my choice?
您的选择是将套接字标记为非阻塞。别无他法。阻塞意味着 'block' 在 socket.You 上发生事件之前执行线程不能根据您的需要阻塞套接字和超时。
使用 select
或 epoll
机制来监视套接字。
Is there any way that I can make connect function return after a time of my choice?
向进程发送信号。
#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, ...);
...
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
在我选择的时间后发挥 return 的作用吗?我尝试从另一个线程调用 close()
但这并没有改变任何东西。
在调用connect()
之前将套接字设置为非阻塞模式,然后可以使用select()
指定超时。 select()
会告诉你连接成功还是超时。如果成功,您可以根据需要将套接字重新置于阻塞模式。如果 failed/timeout,则关闭套接字。
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);
int errCode = 0;
result = connect(tcp_sock, ...);
if (result < 0)
{
errCode = errno;
if (errCode == 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, &wfd, NULL, &timeout);
if (result > 0)
{
socklen_t len = sizeof(errCode);
result = getsockopt(tcp_sock, SOL_SOCKET, SO_ERROR, &errCode, &len);
if (result < 0)
errCode = errno;
else
result = (errCode == 0) ? 0 : -1;
}
else if (result == 0)
{
errCode = ETIMEDOUT;
result = -1;
}
else
{
errCode = errno;
}
}
}
if (result == 0)
{
// connected
fcntl(tcp_sock, F_SETFL, flags);
...
}
else
{
// error, use errCode as needed
...
}
如果花费时间,唯一摆脱连接的方法是使套接字成为非阻塞的。如果是阻塞套接字,你就出不去了。
Is there any way that I can make connect function return after a time of my choice?
您的选择是将套接字标记为非阻塞。别无他法。阻塞意味着 'block' 在 socket.You 上发生事件之前执行线程不能根据您的需要阻塞套接字和超时。
使用 select
或 epoll
机制来监视套接字。
Is there any way that I can make connect function return after a time of my choice?
向进程发送信号。
#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, ...);
...