我使用来自不同线程的gethostbyname()进行了DNS解析的实验。我关闭了网络链接,并在下面运行了程序。输出是这样的
gethostbyname started at 1411234734 gethostbyname started at 1411234734 gethostbyname started at 1411234734 gethostbyname finished at 1411234774 gethostbyname finished at 1411234814 gethostbyname finished at 1411234854
gethostbyname() started at the same time, but finished one by one with 40 sec timeout.
Then i experemented with getaddrinfo(). And it looks like this function doesn't suffer from this problem
getaddrinfo started at 1411235759 getaddrinfo started at 1411235759 getaddrinfo started at 1411235759 getaddrinfo finished at 1411235799 getaddrinfo finished at 1411235799 getaddrinfo finished at 1411235799
So, why I got this result and is this behavior specific for Linux only?
#include <sys/types.h>
#include <sys/socket.h>
#include <netdb.h>
#include <stdio.h>
#include <time.h>
#include <pthread.h>
void *resolve_ghbn(void *host) {
printf("gethostbyname started at %d\n", time(NULL));
struct hostent *rslv = gethostbyname((char*)host);
printf("gethostbyname finished at %d\n", time(NULL));
return NULL;
}
void *resolve_gai(void *host) {
struct addrinfo *result;
printf("getaddrinfo started at %d\n", time(NULL));
int res = getaddrinfo(host, NULL, NULL, &result);
printf("getaddrinfo finished at %d\n", time(NULL));
if (res == 0)
freeaddrinfo(result);
return NULL;
}
int main() {
char *domains[] = {"google.com", "google.cy", "google.us"};
pthread_t threads[3];
int i;
for (i=0; i<3; i++) {
pthread_create(&threads[i], NULL, resolve_ghbn, domains[i]);
}
void *retval;
for (i=0; i<3; i++) {
pthread_join(threads[i], &retval);
}
return 0;
}
最佳答案
getaddrinfo()
函数不共享任何全局/静态变量,因此是可重入的,因此是线程安全的。它将结果返回到使用malloc()
分配的内存中,并且用户负责使用freeaddrinfo()
,后者又使用free()
分配数据。因此,允许您从多个线程同时运行getaddrinfo()
,并且各个实例并行运行。
另一方面,gethostbyname()
返回指向全局/静态数据的指针,从而返回is not reentrant。用户不负责释放数据。因此,不允许您从多个线程同时运行gethostbyname()
。根据您的测试,GNU C库显然可以对调用进行序列化,以避免并行运行导致的错误。
您通常应该避免使用gethostbyname()
,因为getaddrinfo()
在某种程度上已经过时了,但后者至少是glibc中的not a perfect replacement。我建议使用getaddrinfo()
并在适当的地方使用解决方法来解决其错误。
您可以通过检查源代码找到更多信息。
关于c - gethostbyname()进程即使从不同线程中也能一致地解析?,我们在Stack Overflow上找到一个类似的问题:https://stackoverflow.com/questions/25951925/