带超时机制的DNS解析API
根据域名解析出该域名所绑定的IP地址,这个是客户端常做的工作,只有在解析成功之后,才能正确的与服务器端建立连接.
一般常使用getaddrinfo,gethostbyname 之类的API来完成这个工作,但是,这些API都有一个问题,就是都不支持超时机制,假如客户端调用这些API阻塞,给程序会带来影响.
现在想要达到的目标就是:调用API去解析域名,如果在一个时间内不能解析成功,就报错退出.
我查了一下资料,有一些库可以支持这样的要求,但是都需要自己去做DNS解析的工作,也就是需要自己去封包/解包DNS协议报文.显然,这样的事情工作量太大了,不在我考虑的范围之中.
其实系统中有不少这样的API,没有阻塞机制,又不能设置超时参数,有没有一个好的策略,可以既使用这些API,又能给它们加上超时机制.
我看了下APUE中关于sigsetjmp + alarm + siglongjmp的方式来处理这样的问题,自己写了一个简单的demo,看来是可以满足的:
不过这个策略还是有问题的,这个API通过alarm函数设定了一个定时器,超时的时候发送一个SIGALARM信号,如果系统中已经存在了通过alarm定制的定时器,如果解决这些定时器可能发生的冲突问题?如果有更好的办法,欢迎提示.
一般常使用getaddrinfo,gethostbyname 之类的API来完成这个工作,但是,这些API都有一个问题,就是都不支持超时机制,假如客户端调用这些API阻塞,给程序会带来影响.
现在想要达到的目标就是:调用API去解析域名,如果在一个时间内不能解析成功,就报错退出.
我查了一下资料,有一些库可以支持这样的要求,但是都需要自己去做DNS解析的工作,也就是需要自己去封包/解包DNS协议报文.显然,这样的事情工作量太大了,不在我考虑的范围之中.
其实系统中有不少这样的API,没有阻塞机制,又不能设置超时参数,有没有一个好的策略,可以既使用这些API,又能给它们加上超时机制.
我看了下APUE中关于sigsetjmp + alarm + siglongjmp的方式来处理这样的问题,自己写了一个简单的demo,看来是可以满足的:
#include
<
setjmp.h
>
#include < stdio.h >
#include < sys / types.h >
#include < sys / socket.h >
#include < netdb.h >
#include < signal.h >
#include < string .h >
int resolv_name( const char * url, int second);
int main()
{
resolv_name( " www.test2test.com " , 1 );
return 0 ;
}
static sigjmp_buf jmpbuf;
static volatile sig_atomic_t canjump;
static void
sig_alrm( int signo)
{
if ( ! canjump)
return ;
siglongjmp(jmpbuf, 1 ); /* jump back to main, don't return */
canjump = 0 ;
}
int resolv_name( const char * url, int second)
{
struct addrinfo * result = NULL;
int ret;
struct addrinfo addr;
memset( & addr, 0 , sizeof (addr));
addr.ai_socktype = SOCK_STREAM;
if (signal(SIGALRM, sig_alrm) == SIG_ERR)
printf( " signal(SIGALRM) error\n " );
canjump = 1 ;
if (sigsetjmp(jmpbuf, 1 ))
{
printf( " ending main\n " );
return - 1 ;
}
alarm(second);
ret = getaddrinfo(url, NULL, & addr, & result);
canjump = 0 ;
if ( ! ret)
{
struct addrinfo * pCurr = result;
printf( " the \'%s\' ip is:\n " , url);
for (; pCurr; pCurr = pCurr -> ai_next)
{
printf( " %s\n " , inet_ntoa((( struct sockaddr_in * )(pCurr -> ai_addr)) -> sin_addr));
}
}
return 0 ;
}
#include < stdio.h >
#include < sys / types.h >
#include < sys / socket.h >
#include < netdb.h >
#include < signal.h >
#include < string .h >
int resolv_name( const char * url, int second);
int main()
{
resolv_name( " www.test2test.com " , 1 );
return 0 ;
}
static sigjmp_buf jmpbuf;
static volatile sig_atomic_t canjump;
static void
sig_alrm( int signo)
{
if ( ! canjump)
return ;
siglongjmp(jmpbuf, 1 ); /* jump back to main, don't return */
canjump = 0 ;
}
int resolv_name( const char * url, int second)
{
struct addrinfo * result = NULL;
int ret;
struct addrinfo addr;
memset( & addr, 0 , sizeof (addr));
addr.ai_socktype = SOCK_STREAM;
if (signal(SIGALRM, sig_alrm) == SIG_ERR)
printf( " signal(SIGALRM) error\n " );
canjump = 1 ;
if (sigsetjmp(jmpbuf, 1 ))
{
printf( " ending main\n " );
return - 1 ;
}
alarm(second);
ret = getaddrinfo(url, NULL, & addr, & result);
canjump = 0 ;
if ( ! ret)
{
struct addrinfo * pCurr = result;
printf( " the \'%s\' ip is:\n " , url);
for (; pCurr; pCurr = pCurr -> ai_next)
{
printf( " %s\n " , inet_ntoa((( struct sockaddr_in * )(pCurr -> ai_addr)) -> sin_addr));
}
}
return 0 ;
}
不过这个策略还是有问题的,这个API通过alarm函数设定了一个定时器,超时的时候发送一个SIGALARM信号,如果系统中已经存在了通过alarm定制的定时器,如果解决这些定时器可能发生的冲突问题?如果有更好的办法,欢迎提示.