Windows XP Windows 7 Windows 2003 Windows Vista Windows 綜合教學 Linux 系統教學
Windows 10 Windows 8 Windows 2008 Windows NT Windows Server 電腦軟體教學
您现在的位置: Windows教程網 >> Windows教程 >  >> Linux 系統教學 >> Linux 教學

Linux 網路程式設計:gethostbyname 與 getaddrinfo 域名解析對比實戰

編輯:Linux 教學

在 Linux C/C++ 網路程式開發中,域名解析是建立連線的第一步。傳統 gethostbyname 與現代 getaddrinfo 共存多年,二者在介面設計、IPv6 支援、執行緒安全性等方面差異顯著。本文通過原型分析、代碼實戰與最佳實踐,幫助開發者選擇正確工具。

gethostbyname:經典但已棄用

#include <netdb.h>
struct hostent *gethostbyname(const char *name);

結構體 hostent:

  • h_name:正式主機名
  • h_aliases:別名列表
  • h_addrtype:地址族 (AF_INET)
  • h_length:地址長度 (4 bytes)
  • h_addr_list:IPv4 地址陣列 (網路序)

缺陷:
❌ 僅支援 IPv4
❌ 非執行緒安全(靜態緩衝區)
❌ 無法獲取 Socket 類型/協議資訊
❌ 錯誤處理依賴全域 h_errno

getaddrinfo:現代標準介面

int getaddrinfo(const char *node, const char *service,
                const struct addrinfo *hints,
                struct addrinfo **res);

核心優勢:
✅ 協議無關(IPv4/IPv6 雙棧)
✅ 執行緒安全(調用者分配記憶體)
✅ 輸出 addrinfo 鏈表,含 ai_family/ai_socktype/ai_protocol/ai_addr 完整 Socket 參數
✅ 統一錯誤碼,配合 gai_strerror() 易診斷

實戰代碼對比

gethostbyname 範例

struct hostent *hp = gethostbyname("www.example.com");
if (!hp) { herror("gethostbyname"); return -1; }
for (int i=0; hp->h_addr_list[i]; ++i) {
    char ip[INET_ADDRSTRLEN];
    inet_ntop(AF_INET, hp->h_addr_list[i], ip, sizeof(ip));
    printf("%s\n", ip);
}

getaddrinfo 範例(推薦)

struct addrinfo hints = {0}, *res, *p;
hints.ai_family = AF_UNSPEC;     // IPv4/IPv6 皆可
hints.ai_socktype = SOCK_STREAM; // TCP
int err = getaddrinfo("www.example.com", "80", &hints, &res);
if (err) { fprintf(stderr, "%s\n", gai_strerror(err)); return -1; }

for (p=res; p; p=p->ai_next) {
    char ip[INET6_ADDRSTRLEN];
    void *addr = (p->ai_family==AF_INET) ?
        &((struct sockaddr_in*)p->ai_addr)->sin_addr :
        &((struct sockaddr_in6*)p->ai_addr)->sin6_addr;
    inet_ntop(p->ai_family, addr, ip, sizeof(ip));
    printf("%s\n", ip);
}
freeaddrinfo(res); // 必須釋放

選型建議

場景推薦介面理由
新專案/跨平台/長期維護getaddrinfo標準化、IPv6 就緒、執行緒安全
舊代碼維護/極簡 IPv4 工具gethostbyname相容性、代碼量極小
高效能非阻塞解析c-ares / getaddrinfo_a異步非阻塞,避免阻塞事件循環

進階提示

  • AI_ADDRCONFIG 標誌可自動過濾本機不支援的協議族,減少連線失敗。
  • 解析結果建議緩存(TTL 遵循 DNS 記錄),避免頻繁查詢造成延遲。
  • 容器/雲環境中注意 /etc/resolv.conf 與 /etc/nsswitch.conf 配置對解析行為的影響。

拥抱 getaddrinfo,編寫面向未來的網路代碼。

Copyright © Windows教程網 All Rights Reserved