如何摆脱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
函数在我选择的时间后返回?我尝试从另一个线程调用close()
,但这不会改变任何东西。
在调用 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);
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
...
}
有什么方法可以让连接函数在我选择的时间后返回?
向进程发送信号。
#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, ...);
...
如果需要时间,退出连接的唯一方法是使套接字不阻塞。如果是阻塞套接字,则无法退出。
有什么方法可以让连接函数在我选择的时间后返回?
您的选择是将套接字标记为非阻塞。没有其他办法。阻塞意味着"阻塞"执行线程,直到套接字上发生事件。您不能根据需要同时设置阻塞套接字和超时。
使用、select
或epoll
机制来监视套接字。
相关文章:
- 什么时候调用组成单元对象的析构函数
- 对RValue对象调用的LValue ref限定成员函数
- 为什么使用 "this" 指针调用派生成员函数?
- 函数调用中参数的顺序重要吗
- OpenGL - 在抛出"__gnu_cxx::recursive_init_error"实例后终止调用?
- 基于另一个成员参数将函数调用从类传递给它的一个成员
- 为什么我的C#代码在调用回C++COM直到Task时会暂停.等待/线程.加入
- 在c++类上调用void函数
- 为什么 std::unique 不调用 std::sort?
- 我可以调用 bind() 然后在同一个套接字描述符上调用 connect() 吗?
- Qt connect(*发送器,*信号,*接收器,*方法)不调用插槽
- 在UDP套接字上多次调用Connect()以发送到不同的目标地址 - 有效
- 如何摆脱TCP阻塞connect()调用
- 如果插槽对象包含互斥锁和条件变量,则 Boost signals2 connect() 调用编译失败
- 将控件作为成员字段传递给使用新 connect() 调用的方法
- 调用 connect() 时程序崩溃
- 调用connect时的问题会给我一个错误
- 调用socket::connect, socket::bind, socket::listen而不使用getaddrin
- 使用sockaddr_un调用connect(2)时编译错误
- Qt正确的connect()调用