// 通用地址結構
struct sockaddr {
sa_family_t sa_family; // 地址族:AF_INET, AF_INET6
char sa_data[14]; // 協議地址(IP+端口)
};
// IPv4 專用結構(實際編程常用)
struct sockaddr_in {
sa_family_t sin_family; // AF_INET
in_port_t sin_port; // 端口號(網絡序)
struct in_addr sin_addr; // IP 地址(網絡序)
unsigned char sin_zero[8]; // 填充,對齊到 sockaddr 大小
};
struct in_addr {
in_addr_t s_addr; // 32 位 IPv4 地址(網絡序)
};
#include <arpa/inet.h> int inet_aton(const char *cp, struct in_addr *inp); // 字符串 → 網絡序 in_addr char *inet_ntoa(struct in_addr in); // 網絡序 in_addr → 字符串
注意:inet_aton 將結果以網絡序(大端)寫入 inp->s_addr。在小端主機上直接打印 %x 會顯示字節反轉後的值,但實際內存中已是正確的網絡序。
struct in_addr addr;
inet_aton("180.97.33.107", &addr);
printf("Network order: %x\n", addr.s_addr); // 輸出 b461216b(大端)
// 主機為小端,printf 讀取內存低字節在前,顯示 6b2161b4
// 實際網絡傳輸時會發送正確的大端序列
struct in_addr addr;
addr.s_addr = 0xb461216b; // 直接賦值網絡序值
printf("IP: %s\n", inet_ntoa(addr)); // 輸出 180.97.33.107
#include <netdb.h> struct hostent *gethostbyname(const char *name);
hostent 結構包含:官方主機名 h_name、別名列表 h_aliases、地址類型 h_addrtype、地址長度 h_length、地址列表 h_addr_list(網絡序)。
struct hostent *h = gethostbyname("www.baidu.com");
printf("Official name: %s\n", h->h_name);
for (char **alias = h->h_aliases; *alias; alias++)
printf("Alias: %s\n", *alias);
for (char **addr = h->h_addr_list; *addr; addr++) {
struct in_addr in = *(struct in_addr *)*addr; // 強轉後解引用
printf("IP: %s\n", inet_ntoa(in));
}
gethostbyname 不支持 IPv6、非線程安全。新代碼應使用 getaddrinfo(),支持雙棧、異步解析、線程安全。
htons()/htonl() 轉為網絡序sockaddr_in 初始化時務必 memset(&addr, 0, sizeof(addr)) 清零 sin_zeroprintf("%x", addr.sin_addr.s_addr) 觀察網絡序值,而非主機序