ping命令使用到了網絡中的ICMP協議:
關於ICMP介紹看這里:https://www.cnblogs.com/wanghao-boke/p/11670473.html
網絡地址信息
地址信息表示:
網絡傳輸時地址信息包括:
- 地址族(基於IPV4還是IPv6的地址族)
- IP地址
- 端口號
使用相關結構體來紀錄地址信息:
struct sockaddr_in{ sa_family_t sin_family; // 地址族 uint16_t sin_port; // 端口號 struct in_addr sin_addr; // 32位IP地址 char sin_zero[8]; // 不使用 }; struct in_addr{ in_addr_t s_addr; // 32位IP地址 }; struct in_addr{ in_addr_t s_addr; // 32位IP地址 }; #define in_addr_t uint32_t //無符號整型32位
還可以使用以下結構體:
struct sockaddr{ sa_family_t sin_family; // 地址族 char sa_data[14]; // IP地址和端口 };
成員sa_data保存的信息包含IP地址和端口號,剩余部分填充0。
在使用時定義信息地址時使用struct sockaddr_in結構體,然后將該結構體類型轉成struct sockaddr結構體傳遞給網絡編程。
主機字節序與網絡字節序
在CPU中,4字節整型數值1在內存空間保存方式是不同的。
4字節整型數值1可用二進制表示如下:
00000000 00000000 00000000 00000001
而在有些CPU則以倒序保存
00000001 00000000 00000000 00000000
這兩種CPU解析數據的方式分別被稱為
大端序:高位字節存放到低位地址。
小端序:高位字節存放到高位地址
為了使發送和接受雙方主機的CPU在解析數據方式上保持一致,在網絡傳輸數據時約定統一為大端序,這種約定被稱之為網絡字節序。
所以在網路傳輸數據前,需要把數據數組轉換成大端序格式再進行網絡傳輸,接收到網絡數據后,需要轉換本機字節格式然后進行后續處理。該步驟都會有關函數來處理。
我們需要做的就是向struct sockaddr_in結構體變量種填充IP地址和端口數據的時候轉換該格。
具體轉換字節序的函數有以下幾種方式:
unsigned short htons(unsigned short); unsigned short ntohs(unsigned short); unsigned long htonl(unsigned long); unsigned long ntohl(unsigned long);
htonl/htons中h表示(host)主機字節序,n表示(network)網絡字節序,s表示short,l指的是long(linux中long類型和int一樣只占4字節)。
實例:
/*test.c*/ #include<stdio.h> #include<arpa/inet.h> int main() { unsigned short hosts = 0x1234; unsigned short nets; unsigned hostl = 0x12345678; unsigned netl; nets = htons(hosts); netl = htonl(hostl); printf("Host order short: %#x \n", hosts); printf("NetWork order short: %#x \n", nets); printf("Host order long: %#x \n", hostl); printf("NetWork order long: %#x \n", netl); return 0; }
運行結果:
Host order short: 0x1234
NetWork order short: 0x3412
Host order long: 0x12345678
NetWork order long: 0x78563412
擴展:
Intel系統的CPU采用的都是小端序標准。