不同 CPU 架構(x86 為 Little-Endian,網路序為 Big-Endian)導致資料表示差異,Linux 提供四個標準函數統一轉換:
| 函數 | 說明 |
|---|---|
htonl() | 主機長整數 → 網路長整數 |
htons() | 主機短整數 → 網路短整數 |
ntohl() | 網路長整數 → 主機長整數 |
ntohs() | 網路短整數 → 主機短整數 |
命名規則:h=host, n=network, s=short, l=long。在填充 sockaddr_in 結構的 sin_port、sin_addr.s_addr 時務必使用。
hostentstruct hostent {
char *h_name; // 官方主機名
char **h_aliases; // 別名列表
int h_addrtype; // 位址類型 (AF_INET)
int h_length; // 位址長度 (IPv4 為 4)
char **h_addr_list; // IP 位址列表
};
#define h_addr h_addr_list[0] // 第一個 IP 位址
gethostbyname(const char *hostname):域名 → hostent 指標gethostbyaddr(const char *addr, int len, int type):IP 位址(二進位)→ hostent 指標失敗傳回 NULL,錯誤碼存於 h_errno,可用 hstrerror() 取得說明。
inet_aton(const char *cp, struct in_addr *inp):字串 "192.168.0.1" → 二進位存入 inp,成功回 1。inet_ntoa(struct in_addr in):二進位 → 靜態字串指標(不可重入,多執行緒慎用)。現代程式建議使用 inet_pton()/inet_ntop() 支援 IPv6 並具執行緒安全。
struct servent {
char *s_name; // 服務官方名稱
char **s_aliases; // 別名
int s_port; // 埠號 (網路序)
char *s_proto; // 協議名 (tcp/udp)
};
getservbyname(const char *name, const char *proto):服務名 → 結構(如 "http", "tcp" → 80)。getservbyport(int port, const char *proto):埠號 → 結構。#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <netdb.h>
#include <arpa/inet.h>
#include <netinet/in.h>
int main(int argc, char **argv) {
if (argc < 2) {
fprintf(stderr, "Usage: %s hostname|IP ...\n", argv[0]);
exit(EXIT_FAILURE);
}
struct sockaddr_in addr;
struct hostent *host;
char **alias;
for (argv++; *argv; argv++) {
// 嘗試視為 IP 位址
if (inet_aton(*argv, &addr.sin_addr)) {
host = gethostbyaddr((char *)&addr.sin_addr, 4, AF_INET);
printf("Address information of IP %s\n", *argv);
} else { // 視為主機名
host = gethostbyname(*argv);
printf("Address information of host %s\n", *argv);
}
if (!host) {
fprintf(stderr, "No address information for %s\n", *argv);
continue;
}
printf("Official name: %s\n", host->h_name);
printf("Aliases: ");
for (alias = host->h_aliases; *alias; alias++)
printf("%s ", *alias);
printf("\nIP addresses: ");
for (alias = host->h_addr_list; *alias; alias++)
printf("%s ", inet_ntoa(*(struct in_addr *)*alias));
printf("\n\n");
}
return 0;
}
gcc -o hostinfo hostinfo.c
./hostinfo www.google.com 8.8.8.8