網路序 = Big-Endian。主機序視 CPU 而定。四大轉換函式:
uint16_t htons(uint16_t hostshort); // Host to Network Short
uint32_t htonl(uint32_t hostlong); // Host to Network Long
uint16_t ntohs(uint16_t netshort); // Network to Host Short
uint32_t ntohl(uint32_t netlong); // Network to Host Long
鐵律:所有放入 sockaddr 結構的 sin_port、sin_addr.s_addr 必須經 htons/htonl 轉換。
struct addrinfo 詳解現代 Socket 程式設計的核心結構,支援 IPv4/IPv6 協議無關寫法。欄位包括 ai_family、ai_socktype、ai_protocol、ai_addr (指向 sockaddr)、ai_next (鏈表)。由 getaddrinfo() 填充,用畢需 freeaddrinfo() 釋放。
struct sockaddr 家族struct sockaddr {
sa_family_t sa_family; // AF_INET, AF_INET6
char sa_data[14]; // 14 bytes protocol address
};
sockaddr_instruct sockaddr_in {
sa_family_t sin_family; // AF_INET
in_port_t sin_port; // 網路序 port
struct in_addr sin_addr; // IPv4 位址
unsigned char sin_zero[8]; // 填充對齊
};
struct in_addr { uint32_t s_addr; };
使用時:memset(&sin, 0, sizeof(sin)) 或 bzero 清零,再填欄位。
sockaddr_in6struct sockaddr_in6 {
sa_family_t sin6_family; // AF_INET6
in_port_t sin6_port;
uint32_t sin6_flowinfo;
struct in6_addr sin6_addr; // 128-bit
uint32_t sin6_scope_id; // 介面範圍 ID
};
struct in6_addr { unsigned char s6_addr[16]; };
sockaddr_storagestruct sockaddr_storage {
sa_family_t ss_family;
char __ss_padding[128-sizeof(sa_family_t)];
__ss_align; // 強制對齊
};
足以容納 IPv4/IPv6 任何地址。用於 accept()、recvfrom() 等輸出參數,事後檢查 ss_family 決定轉型為 sockaddr_in* 或 sockaddr_in6*。
getaddrinfo() 取代 gethostbyname() / inet_addr()。sin_zero / __ss_padding 必須清零,否則可能導致比較錯誤。sin6_scope_id(介面索引)。