三、總結
ping命令的工作原理:向網路上的另乙個主機系統傳送icmp報文,如果指定系統得到了報文,它將把報文一模一樣地傳回給傳送者,這有點象潛水艇聲納系統中使用的發聲裝置
這裡就得說下icmp報文的格式,我們需要自己手動組乙個icmp的包發給主機進行探測
型別(8位)
編碼(8位)
校驗和(16位)
識別符號順序號
可選資料
icmp主要分為差錯報文和詢問報文,資料格式如上表所示。差錯報文提供一組易懂的出錯報告資訊,以快速診斷出出錯原因。詢問報文分為請求回顯(ping請求)、回顯應答(ping應答)、位址掩碼請求、位址掩碼應答等等。我們這裡主要是測試主機可答性,實現ping功能,主要介紹下詢問報文的格式組包:
1. icmp報文的前4個位元組是統一的格式,共有三個字段:即型別,**和檢驗和。
2. 8位型別和8位**字段一起決定了icmp報文的型別。
型別8,**0:表示回顯請求(ping請求)
型別0,**0:表示回顯應答(ping應答)
3. 16位的檢驗和字段:包括資料在內的整個icmp資料報的檢驗和;其計算方法和ip頭部檢驗和的計算方法一樣的。
4. 識別符號和順序號:icmp報文中的識別符號和序列號字段由傳送端任意選擇設定,這些值在應答中將被返回,這樣,傳送端就可以把應答與請求進行匹配。
下面顯示組包**
struct icmp *picmp;
/* 型別和**分別為icmp_echo,0代表請求回送 */
picmp->icmp_type = icmp_echo;
picmp->icmp_code =0;
picmp->icmp_cksum =0;
//校驗和
picmp->icmp_seq =1;
//序號
picmp->icmp_id =
getpid()
;//取程序號作為標誌
ptime =
(struct timeval *
)picmp->icmp_data;
gettimeofday
(ptime,
null);
//資料段存放傳送時間
picmp->icmp_cksum =
compute_cksum
(picmp)
;
icmp報文傳輸在ip層,所以主機需要通過在網路層進行連線和報文的傳送,另外ping操作可以直接對網域名稱進行操作,如果下發的是網域名稱在連線之前還要先對網域名稱進行ip的轉換。
操作**如下:
struct hostent * phost =
null
;// 儲存主機資訊
struct sockaddr_in dest_addr;
// ipv4專用socket位址,儲存目的位址
in_addr_t inaddr;
socket
(pf_inet, sock_raw, ipproto_icmp));
dest_addr.sin_family = af_inet;
/* 將點分十進位制ip位址轉換為網路位元組序 */if(
(inaddr =
inet_addr
(ipaddr)
)== inaddr_none)
memmove
(&dest_addr.sin_addr, phost->h_addr_list[0]
, phost->h_length);}
else
picmp =
(struct icmp*
)sendbuffer;
sendto
(sock_icmp, sendbuffer, icmp_len,0,
(struct sockaddr *
)dest_addr,
sizeof
(struct sockaddr_in));
// 報文傳送
當主機能收到報文時,說明目的主機可達,驗證返回報文中的識別符號和自己之前發出去的是否一致,來判斷當次傳輸是否正常。由於我們這裡只是為了模擬ping功能,實現源主機到目的主機的可達性,就沒有去解析一些ping的時間等
流程如下:
int
recvepacket
(int sock_icmp,
struct sockaddr_in *dest_addr)
;struct timeval select_timeout;
fd_set rset;
select_timeout.tv_sec =7;
select_timeout.tv_usec =0;
fd_zero
(&rset)
;fd_set
(sock_icmp,
&rset);if
(select
(sock_icmp+1,
&rset,
null
,null
,&select_timeout)
<=0)
if((recvbytes =
recvfrom
(sock_icmp, recvbuffer, recv_buffer_size,0,
(struct sockaddr *
)dest_addr,
&addrlen)
)<0)
gettimeofday
(&recvtime,
null);
if(unpack
(&recvtime,recvbuffer)==-
1)return recvbytes;
}int
unpack
(struct timeval *recvtime,
char
*recvbuffer)
else
return-1
;}
本文主要通過原始碼實現了ping功能,可以用來檢測一些主機的可達性,可以直接在應用層上使用。如果後續有ping測試的時間上的需求,可以自己再去對時間進行計算。 C STL PJ 原始碼 list 原理解析
了解 c list 是屬於雙向迴圈鍊錶,就是 雙向鍊錶 與 迴圈鍊錶 的結合體。所以我們必須對 雙向鍊錶 與 迴圈鍊錶 了解必要的知識。下篇我們就解析 c list容器的奧秘吧!雙向鍊錶 1.雙向鍊錶的結構 表示的鍊錶的 前驅 prev 儲存位址 表示的鍊錶儲存的 值的部分 value 表示的鍊錶的...
C STL PJ 原始碼 list 原理解析2
1.什麼是雙向迴圈列表?雙向鍊錶是對與 迴圈鍊錶 與 雙向鍊錶 的結合 注意 如果對 迴圈鍊錶 與 雙向鍊錶 不太熟識去看之前的文章!這裡對鍊錶不做過多解析!2.鍊錶的架構!prev 前驅 value 值 next 後繼指標 3.直接上 這裡不會對 萃取 進行分析,所以我把 萃取 去掉。本章節對原始...
SpringMVC原理 解析請求引數(原始碼分析)
在使用springmvc的時候,我們經常編寫controller層的介面,並使用一些註解傳遞一些引數,那麼這些引數是怎麼封裝進我們的請求的呢?springmvc是怎麼解析這些引數的呢?本文主要通過原始碼分析springmvc解析請求引數的全過程。編寫乙個controller類,裡面寫上乙個介面方法 ...