一、方法分析
在Linux环境下gethostbyname函数是用来向DNS查询一个域名的IP地址。 由于DNS的查询方式是递归查询,在网络不通的情况下会导致gethostbyname函数在查询一个域名时出现严重超时问题。而该函数又不能像connect和read等函数那样通过setsockopt或者select函数那样设置超时时间,因此常常成为程序开发的瓶颈。
在多线程环境下,gethostbyname会出现一个非常严重的问题,就是如果有一个线程的gethostbyname发生阻塞,其它线程都会在gethostbyname处发生阻塞,直到该线程的gethostbyname函数返回为止。针对这样的问题我们应该怎么处理呢?
下面介绍两种方法:
1、 使用alarm设定信号,如果超时就用sigsetjmp和siglongjmp跳过gethostbyname函数。
2、 独立开启一个线程来调用gethostbyname函数,该线程除了调用此函数外,不做任何事情。
二、方法介绍
1、alarm设定信号方法
(1)、sigsetjmp和siglongjmp概述
sigsetjmp: 参数为非0的时候,会保存进程的当前信号屏蔽字
siglongjmp: 恢复保存的信号屏蔽字
(2)、使用方法
-
#include <setjmp.h>
-
#include <time.h>
-
-
static sigjmp_buf jmpbuf;
-
static void alarm_func()
-
{
-
siglongjmp(jmpbuf, 1);
-
}
-
-
static struct hostent *gngethostbyname(char *HostName, int timeout)
-
{
-
struct hostent *lpHostEnt;
-
-
signal(SIGALRM, alarm_func);
-
if(sigsetjmp(jmpbuf, 1) != 0)
-
{
-
alarm(0); /* 取消闹钟 */
-
signal(SIGALRM, SIG_IGN);
-
return NULL;
-
}
-
alarm(timeout); /* 设置超时时间 */
-
lpHostEnt = gethostbyname(HostName);
-
signal(SIGALRM, SIG_IGN);
-
-
return lpHostEnt;
-
}
2、多线程方法
-
#include <stdio.h>
-
#include <stdlib.h>
-
#include <netdb.h>
-
#include <pthread.h>
-
-
-
char address[64] = {"0.0.0.0"};
-
-
void *_GetHostName2Ip(void *HostName)
-
{
-
char *pstHostName = NULL;
-
-
struct hostent *hptr;
-
-
pstHostName = (char *)HostName;
-
hptr = gethostbyname(pstHostName);
-
if(NULL == hptr)
-
{
-
pthread_exit(-1);
-
}
-
-
inet_ntop(hptr->h_addrtype, hptr->h_addr, address, 32);
-
pthread_exit(0);
-
}
-
-
int main()
-
{
-
int kill_err = 0;
-
static char cHostName[256]; /* 域名地址,根据需要自己设定 */
-
-
pthread_t gethostname;
-
-
kill_err = pthread_kill(gethostname, 0);
-
if(ESRCH == kill_err) /* 判断线程是否存在 */
-
{
-
pthread_create(&gethostname, NULL, _GetHostName2Ip, (void *)cHostName);
-
}
-
else if(EINVAL == kill_err) /* 信号非法 */
-
{
-
return -1;
-
}
-
-
printf("address = %s\n", address);
-
-
return 0;
-
}
通过实际应用与测试,在多线程环境下,多线程方法是最适用的,如果应用alarm信号可能会导致无法预知的问题。需要说明指出的是:多线程方法和alarm信号设定只是在嵌入式设备中进行测试过,如果使用到其它地方请详加仔细验证。由于知识有限,难免有疏漏和错误,请读者给予指正......
阅读(6673) | 评论(0) | 转发(0) |