域名介紹
在網絡通信中,需要用到ip加port,但是ip并不方便記憶,于是我們常用域名來對應一個ip
例如:www.baidu.com? ? 對應? ? 156.36.56.98(隨便寫的)
com: 一級域名. 表示這是一個企業域名. 同級的還有 "net"(網絡提供商), "org"(非盈利組織) 等.
baidu: 二級域名, 公司名.
www: 只是一種習慣用法.
域名解析
域名解析分為兩步
1.查本地?/etc/hosts
互連網信息中心(SRI-NIC)會管理一個?hosts 文件,本地主機只需要定期下載即可,里面就是域名和ip的對應
2.使用DNS技術
如果/etc/hosts找不到,那就去向本地DNS服務器發送請求進行查詢,本地DNS服務器通常以守護進程形式存在
ICMP協議
ICMP 的報文格式?
標準 ICMP Echo Reply 報文格式?
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
| Type(0) | Code(0) | Checksum |
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
| Identifier | Sequence Number |
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
| Data (可變長度,通常包含時間戳或填充字節) |
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
ping 命令
ping www.baidu.com
ping命令過程分析:
在終端上寫下了這幾個字母,隨著按下回車,終端模擬器將這幾個字母write進主設備,然后驅動程序將主設備數據寫進從設備,喚醒從設備等待隊列上的進程也就是shell,然后shell讀出來,分割字符串,然后創建子進程,進程替換為ping進程,域名通過命令行參數傳給了ping進程,然后ping進程去/etc/hosts文件里面查找域名對應ip,如果找不到就向本地DNS守護進程發消息,然后DNS進程開始詢問服務器,最后得到對應ip。ping進程接下來的操作如下:
步驟 1:創建原始套接字??
int sock = socket(AF_INET, SOCK_RAW, IPPROTO_ICMP);
if (sock < 0) {perror("socket"); // 需 root 權限或 CAP_NET_RAW 能力exit(1);
}
??步驟 2:構造 ICMP 報文??
- ??報文結構??:
0 1 2 3 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ | Type(8) | Code(0) | Checksum | +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ | Identifier | Sequence Number | +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ | Payload (可選) | +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
- ??字段說明??:
- ??Type=8, Code=0??:表示?
Echo Request
。 - ??Identifier??:通常為進程 PID(用于響應能夠查找到對應套接字)。
- ??Sequence Number??:遞增序列號(區分多次請求)。
- ??Checksum??:ICMP 校驗和(需手動計算)。
- ??Type=8, Code=0??:表示?
??步驟 3:發送報文??
struct sockaddr_in dest_addr;
dest_addr.sin_family = AF_INET;
dest_addr.sin_addr.s_addr = inet_addr("93.184.216.34"); // 目標 IP// 發送 ICMP 報文
sendto(sock, icmp_packet, sizeof(icmp_packet), 0, (struct sockaddr*)&dest_addr, sizeof(dest_addr));
??步驟 4:接收 Echo Reply??
char recv_buf[1024];
struct sockaddr_in src_addr;
socklen_t addr_len = sizeof(src_addr);// 阻塞等待響應(內核通過 Identifier 匹配報文)
recvfrom(sock, recv_buf, sizeof(recv_buf), 0, (struct sockaddr*)&src_addr, &addr_len);
ping進程在應用層創建好原始套接字,并且創建好ICMP報文,然后用sendto發送,然后經過ip層和數據鏈路層封裝后發出去,當目標主機收到后,經數據鏈路層和ip層的解包,交給了ICMP協議的接口,檢查ICMP頭里的類型,發現是請求,那就構建對應的ICMP響應,然后經IP協議和以太網協議的封裝又發回去,源主機收到后開始解包,到ICMP協議層時,根據OS維護的hash表,通過響應里的identifier標識符,找到對應的套接字,然后將ICMP報文寫進套接字接收緩沖區,并喚醒等待隊列上的進程,ping進程recvfrom從接收緩沖區里讀出來完整的ICMP報文,然后根據ICMP報文的內容,write寫東西到從設備,終端驅動將從設備數據拷到主設備,然后喚醒終端模擬器,終端模擬器再將東西打到終端上,這就是一次發送數據測試,ping進程會不停發送echo request,并設置序列號來區分這些請求3
??完整流程:ping
?命令的 ICMP 請求與響應全鏈路解析??
??1.?ping
?進程發送 ICMP Echo Request??
??(1)應用層(用戶態)??
??創建原始套接字??
int sock = socket(AF_INET, SOCK_RAW, IPPROTO_ICMP);
- ??權限??:需有
CAP_NET_RAW
?(/bin/ping
?已默認配置)。 - ??作用??:繞過傳輸層,直接操作網絡層(IP)數據包。
- ??權限??:需有
??構造 ICMP Echo Request??
- ??報文結構??:
Type=8 (Echo Request), Code=0
Identifier=進程PID, Sequence=遞增序號
Payload=時間戳或填充數據
- ??計算校驗和??:覆蓋整個 ICMP 報文。
- ??報文結構??:
??發送請求??
sendto(sock, icmp_req, sizeof(icmp_req), 0, &dest_addr, addr_len);
??(2)內核協議棧處理??
??IP 層封裝??
- 添加 IP 頭部:
- 源/目標 IP、TTL(默認 64)、協議號?
1
(ICMP)。
- 源/目標 IP、TTL(默認 64)、協議號?
- 查詢路由表,確定下一跳 ip?地址和發送接口。
- 添加 IP 頭部:
??數據鏈路層封裝??
- 添加以太網幀頭:源/目標 MAC 地址、類型?
0x0800
(IPv4)。 - 通過網卡驅動(如?
eth0
)發送到物理鏈路。
- 添加以太網幀頭:源/目標 MAC 地址、類型?
??2. 目標主機處理與響應??
??(1)網絡接口接收??
??網卡(數據鏈路層)??
- 檢查目標 MAC 地址,若匹配則接收,剝離以太網幀頭。
- 將 IP 數據包交給內核網絡協議棧。
??IP 層解包??
- 校驗 IP 頭部(版本、校驗和、目標 IP)。
- 若 TTL 減至 0,丟棄并返回?
ICMP Time Exceeded
(Type=11)。 - 若目標 IP 匹配本機,剝離 IP 頭,根據協議類型是
1,
?交給 ICMP 模塊。
??(2)ICMP 協議處理??
??解析 ICMP 報文??
- 檢查?
Type=8
(Echo Request),Code=0
。 - 內核自動構造?
Echo Reply
(Type=0),保持相同的?Identifier
?和?Sequence
。
- 檢查?
??發送響應??
- IP 層封裝:源/目標 IP 互換,TTL 重置(如 64)。
- 數據鏈路層封裝:通過 ARP 獲取源主機的 MAC 地址。
- 網卡發送響應包。
??3. 源主機接收響應??
??(1)網絡接口接收??
??網卡收包??
- 過濾目標 MAC,剝離以太網幀頭,IP 層校驗后交給 ICMP 模塊。
??ICMP 協議匹配??
- 內核根據?
Identifier
(如 PID?1234
)查找原始套接字。 - 將報文寫入套接字接收緩沖區。
- 內核根據?
??(2)喚醒?ping
?進程??
??從阻塞中恢復??
ping
?進程此前因?recvfrom()
?阻塞,被內核移至就緒隊列。- 從接收緩沖區讀取?
Echo Reply
?數據。
??計算 RTT(往返時間)??
- 對比當前時間與請求報文中的時間戳(Payload),得到延遲。
??(3)終端輸出??
??
ping
?進程格式化輸出??64 bytes from 93.184.216.34: icmp_seq=1 ttl=53 time=11.3 ms
ttl
:從響應 IP 頭部提取。time
:RTT 計算結果。
??終端顯示流程??
ping
?調用?write()
?將結果寫入標準輸出(文件描述符?1
)。- 終端驅動(如?
tty
)將數據從 ??從設備??(進程緩沖區)拷貝到 ??主設備??(終端顯示器)。 - 終端模擬器(如?
xterm
)渲染最終字符。
補充說明
1.ping
?超時??:內核未收到?Echo Reply
,recvfrom()
?超時后停止等待(等待默認?1 秒),靠sendto重發請求,也就是說ICMP協議是沒有超時重傳的功能的,真正能使其超時重傳的是ping進程邏輯
2.ping發送請求到目標主機,目標主機通過硬件中斷的協議棧就處理了該請求,根本就沒涉及到進程和應用層邏輯
3.ping進程本身處理響應卻是寄托協議棧加上進程和應用層邏輯,還使用了套接字