由于我似乎无法找到原始问题的解决方案,因此我尝试做一些解决方法。我只是想为 TCP 套接字的
connect()
调用设置超时。
connect()
被阻塞,但直到通常的 75 秒超时为止,我想定义我自己的。select()
,它可以解决超时问题,但我无法建立连接(这是我最初的问题,如here所述)。所以现在我找到了另一种方法来处理它:只需执行一个阻塞的
connect()
调用,但用这样的警报中断它:
signal(SIGALRM, connect_alarm);
int secs = 5;
alarm(secs);
if (connect(m_Socket, (struct sockaddr *)&addr, sizeof(addr)) < 0 )
{
if ( errno == EINTR )
{
debug_printf("Timeout");
m_connectionStatus = STATUS_CLOSED;
return ERR_TIMEOUT;
}
else
{
debug_printf("Other Err");
m_connectionStatus = STATUS_CLOSED;
return ERR_NET_SOCKET;
}
}
与
static void connect_alarm(int signo)
{
debug_printf("SignalHandler");
return;
}
这是我在互联网上的 stackoverflow 上的一个线程 here 中找到的解决方案。如果我使用此代码,程序将启动计时器,然后进入
connect()
调用。 5 秒后,信号处理程序被触发(如控制台上的 printf()
所示),但此后程序仍保留在 connect()
函数中 75 秒。实际上,每个描述都说 connect_alarm()
应该中断 connect()
功能,但在我的情况下似乎并非如此。有什么办法可以得到我的问题想要的结果吗?
signal
是一个严重未指定的接口,应在新代码中避免。在某些版本的 Linux 上,我相信它提供了“BSD 语义”,这意味着(除其他外)默认提供 SA_RESTART
。
sigaction
代替,不要指定 SA_RESTART
,就可以开始了。
...
好吧,除了普遍的脆弱性和不可避免的竞争条件之外。
connect
将为 任何信号返回
EINTR
,而不仅仅是 SIGALARM
。更麻烦的是,如果系统负载很重,调用 alarm
和调用 connect
之间可能需要超过 5 秒的时间,这样你就会错过信号并永远阻塞在 connect
中.
您之前的尝试,使用带有
connect
和 select
的非阻塞套接字,是一个更好的主意。我建议调试它。
alarm(2)
相对容易(减少信号处理和系统调用中断的痛苦),但超时 TCP 连接尝试的更有效方法是 non-blocking connect
,它也允许您启动多个连接并等待所有连接,一次处理一个成功和失败。