C Network Programming — IP address 轉換篇
3 min readApr 28, 2024
- in_addr_t inet_addr(const char *cp); 把一個字串形式的 IP 轉成 IPv4 in_addr_t, 例如 “192.168.2.1” 轉成 192.168.2.1 (in_addr_t),通常 in_addr_t 是 unsigned long
- char * inet_ntoa(struct in_addr in); 上面動作的相反,把 in_addr 轉成字串形式
- int inet_aton(const char *cp, struct in_addr *pin); 類似 inet_addr, 但是不是回傳 in_addr,而是直接把它給 pin,也就是第二個參數。成功回傳 0
- int inet_pton(int af, const char *src, void *dst); 把 printable address 轉成二進位,可以支援 IPv4/6,類似 inet_aton。成功回傳 1
- const char * inet_ntop(int af, const void *src, char *dst, size_t size); 上面相反,可以支援 IPv4/6,把 src 轉成 printable address 放在 dst,並且回傳 dst pointer,失敗回傳 NULL
所以我們可以說, IP 有兩種表示方式
- “192.168.2.1” or “FF::00” 這種 printable address (char 字串)
- 二進位,in_addr or in6_addr
如果要寫 IPv4/6 compatible 程式,盡量不要用上面這些 function,尤其是前四個不支援 IPv6 的函式,後兩個函式需要用到 if else 來判慣 AF_* 因此也不是太合適,盡量使用 independent API 像是 getnameinfo 來代替使用
int getnameinfo(const struct sockaddr *sa, socklen_t salen, char *host, size_t hostlen, char *serv, size_t servlen, int flags);
它會根據 sockaddr 的回傳 ip and port 的 printable format
host 返回 domain name (沒有 domain name 則是 ip) and serv 返回 service name (如果 port 有對應的 service,沒有則還是 port number),都是字串。
所以可以用 getnameinfo 把 socakaddr (常用 getaddrinfo 獲得)的 IP address and Port address 轉成 printable address,通常原本二進位 address 就用 getaddrinfo 得到。
getservbyport and gethostbyaddr 也可以用 getnameinfo 代替。