2014-09-20 45 views
1

我對來自不同線程的gethostbyname()進行了DNS解析實驗。我關閉了網絡鏈接並在下面運行程序。和輸出是這樣gethostbyname()進程甚至從不同線程處理一致解析?

 
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()開始在同一時間,而是由一個具有40秒超時完成一個。

然後,我使用getaddrinfo()進行了訓練。它看起來像此函數不存在這種問題

 
getaddrinfo started at 1411235759 
getaddrinfo started at 1411235759 
getaddrinfo started at 1411235759 
getaddrinfo finished at 1411235799 
getaddrinfo finished at 1411235799 
getaddrinfo finished at 1411235799 

這麼辛苦,爲什麼我得到這個結果,併爲這種行爲的具體僅供Linux呢?

#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; 
} 
+2

使用'getaddrinfo()'或使用全局互斥鎖。行爲有什麼不同,我發現這兩種情況都有40秒超時,以及如何關閉網絡鏈接以及如何檢查它是否已關閉? – 2014-09-20 18:20:19

+0

嘿,我現在看到它。我會準備一個答案。 – 2014-09-20 18:28:12

回答

3

getaddrinfo()功能不共享任何全局/靜態變量,因此重入的,因此一個線程安全的。它返回使用malloc()分配的內存中的結果,並且用戶負責使用freeaddrinfo(),後者又使用free()分配數據。因此,您可以同時從多個線程運行getaddrinfo(),並且各個實例並行運行。

另一方面,gethostbyname()返回指向全局/靜態數據的指針,因此返回is not reentrant。用戶不負責釋放數據。因此不允許同時從多個線程運行gethostbyname()。根據您的測試,GNU C庫顯然會對這些調用進行序列化,以避免平行運行導致的錯誤。

您通常應該避免使用gethostbyname(),因爲它有點過時getaddrinfo(),但後者是not a perfect replacement,至少在glibc。我會建議使用getaddrinfo()並在適當的地方爲其錯誤採用解決方法。

您可以通過檢查源代碼來了解更多信息。