那谁的技术博客

感兴趣领域:高性能服务器编程,存储,算法,Linux内核
随笔 - 210, 文章 - 0, 评论 - 1183, 引用 - 0
数据加载中……

带超时机制的DNS解析API

根据域名解析出该域名所绑定的IP地址,这个是客户端常做的工作,只有在解析成功之后,才能正确的与服务器端建立连接.

一般常使用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;
}


不过这个策略还是有问题的,这个API通过alarm函数设定了一个定时器,超时的时候发送一个SIGALARM信号,如果系统中已经存在了通过alarm定制的定时器,如果解决这些定时器可能发生的冲突问题?如果有更好的办法,欢迎提示.



posted on 2009-11-07 19:28 那谁 阅读(9445) 评论(5)  编辑 收藏 引用 所属分类: Linux/Unix

评论

# re: 带超时机制的DNS解析API[未登录]  回复  更多评论   

可以用libevent的那个dns库...
2009-11-09 01:20 | bobo

# re: 带超时机制的DNS解析API  回复  更多评论   

关键问题是有些 dns 解析失败,有时返回 127.0.0.1 .

2009-11-18 15:55 | hzh

# re: 带超时机制的DNS解析API  回复  更多评论   

查了一下 可以通过alarm的返回值来判断是否已经通过alarm定制了定时器
SYNOPSIS
#include <unistd.h>
unsigned alarm(unsigned seconds);

RETURN VALUE
If there is a previous alarm() request with time
remaining, alarm() shall return a non-zero value that
is the number of seconds until the previous request
would have generated a SIGALRM signal. Otherwise,
alarm() shall return 0.
2010-04-14 15:47 | bryan

# re: 带超时机制的DNS解析API  回复  更多评论   

多线程怎么办
2010-12-09 13:59 | sss

# re: 带超时机制的DNS解析API  回复  更多评论   

超时后原来创建的socket套接字无法关闭,会造成句柄被用完的问题。
2014-12-01 14:51 | shifu

只有注册用户登录后才能发表评论。
网站导航: 博客园   IT新闻   BlogJava   知识库   博问   管理