AF_INET 域 Socket 通訊涉及不同機器架構的位元組序差異:網路傳輸統一用大端序,主機序視 CPU 而定(x86 為小端)。系統提供四大轉換函式自動處理,本文詳細解析用法並實測驗證。
| 函式 | 意義 | 資料型別 |
|---|---|---|
htonl | Host TO Network Long | uint32_t (32-bit) |
htons | Host TO Network Short | uint16_t (16-bit) |
ntohl | Network TO Host Long | uint32_t |
ntohs | Network TO Host Short | uint16_t |
標頭檔:<arpa/inet.h>(Linux/macOS)或 <winsock2.h>(Windows)。
智慧特性:若主機序已為大端,函式內部不實際轉換,直接回傳原值。
#include
#include // Linux/macOS
// #include // Windows 需連結 ws2_32.lib
void print_bytes(const char *label, const void *data, size_t len) {
const unsigned char *p = data;
printf("%s\n", label);
for (size_t i = 0; i < len; ++i)
printf("[%p] = 0x%02x\n", p + i, p[i]);
puts("");
}
int main() {
uint32_t host_val = 0x12345678;
print_bytes("主機序 (Host Order):", &host_val, sizeof(host_val));
uint32_t net_val = htonl(host_val);
print_bytes("網路序 (Network Order):", &net_val, sizeof(net_val));
uint32_t back_val = ntohl(net_val);
print_bytes("轉回主機序:", &back_val, sizeof(back_val));
return 0;
}
主機序 (Host Order):
[0x7ffc...] = 0x78
[0x7ffc...] = 0x56
[0x7ffc...] = 0x34
[0x7ffc...] = 0x12
網路序 (Network Order):
[0x7ffc...] = 0x12
[0x7ffc...] = 0x34
[0x7ffc...] = 0x56
[0x7ffc...] = 0x78
轉回主機序:
[0x7ffc...] = 0x78
[0x7ffc...] = 0x56
[0x7ffc...] = 0x34
[0x7ffc...] = 0x12
明顯可見:主機序為小端(低位在低址),網路序為大端(高位在低址),htonl 正確完成雙向轉換。
sockaddr_in 結構struct sockaddr_in addr;
addr.sin_family = AF_INET;
addr.sin_port = htons(8080); // 連接埠必須轉網路序
addr.sin_addr.s_addr = htonl(INADDR_ANY); // IP 位址轉網路序 (INADDR_ANY=0 無影響)
uint16_t peer_port = ntohs(addr.sin_port);
uint32_t peer_ip = ntohl(addr.sin_addr.s_addr);
sin_port 必須用 htons,否則大端機器上連線失敗。htonl 會導致雙重反轉。sin_addr.s_addr 需用 htonl/ntohl,勿直接指派主機序整數。WSAStartup 並連結 ws2_32.lib。位元組序轉換是跨平台網路程式的基石。善用 htonl/htons/ntohl/ntohs,配合 getaddrinfo 等現代 API,可寫出可攜、健壯的 Socket 程式。