計算機(jī)網(wǎng)絡(luò)課程設(shè)計-----基于icmp的ping設(shè)計_第1頁
已閱讀1頁,還剩18頁未讀, 繼續(xù)免費閱讀

下載本文檔

版權(quán)說明:本文檔由用戶提供并上傳,收益歸屬內(nèi)容提供方,若內(nèi)容存在侵權(quán),請進(jìn)行舉報或認(rèn)領(lǐng)

文檔簡介

1、<p>  編程實現(xiàn)基于ICMP的PING</p><p>  學(xué)生姓名: 指導(dǎo)老師:</p><p>  摘 要 本次課程設(shè)計主要是基于Linux系統(tǒng),使用編程語言C語言,編寫一個實驗程序,實現(xiàn)基于ICMP報文的PING的類似功能。本文主要介紹了ICMP報文,PING功能的相關(guān)原理,根據(jù)設(shè)計要求,用C語言編程運行、仿真,通過觀察實驗結(jié)果,從而判定本次設(shè)計成功完成任務(wù)。通過

2、這次計算機(jī)網(wǎng)絡(luò)方面的課程設(shè)計,提高了我們對網(wǎng)絡(luò)領(lǐng)域的認(rèn)識,有利于培養(yǎng)我們在該方面的設(shè)計能力。一人一題特別有利于鍛煉我們獨立分析問題和解決問題的能力。設(shè)計過程的復(fù)雜加老師的嚴(yán)格要求有益于培養(yǎng)我們嚴(yán)謹(jǐn)?shù)墓ぷ髯黠L(fēng)。</p><p>  關(guān)鍵詞 Linux;C語言;ICMP;PING</p><p>  Programming PING capabilities based on ICMP pr

3、otocol</p><p>  Student Name:Li minghong Instructor:Long jizheng</p><p>  Abstract The curriculum design is mainly based on the Linux system, use the programming language C language, write a te

4、st program, packet-based ICMP PING similar function. This paper describes the ICMP message, PING function of relevant principles, according to design requirements, the C programming language to run the simulation, by obs

5、erving the results, which determine the success of this design task. Through this computer network design aspects of the curriculum, improve our knowledge in th</p><p>  Keywords Linux;C language;ICMP;PING&

6、lt;/p><p><b>  1 引 言</b></p><p>  當(dāng)現(xiàn)代社會逐漸變?yōu)榫哂懈叨鹊南嗷ヒ蕾嚨木薮缶W(wǎng)絡(luò)時,我們所生活的世界無法不變成一個被計算機(jī)網(wǎng)絡(luò)緊密聯(lián)結(jié)起來的世界。計算機(jī)網(wǎng)絡(luò)從技術(shù)角度來說,是作為一種布局,將經(jīng)有關(guān)聯(lián)但相距遙遠(yuǎn)的事物通過通信線路連接起來,但是對網(wǎng)絡(luò)的思考決不是傳統(tǒng)的二維平面思維甚至三維的球面思維所能達(dá)到的。</p><

7、;p>  在信息時代,網(wǎng)絡(luò)的生命在于其安全性和可靠性。計算機(jī)網(wǎng)絡(luò)最重要的方面是它向用戶所提供的信息服務(wù)及其所擁有的信息資源,網(wǎng)絡(luò)連接在給用戶帶來方便的同時,也給網(wǎng)絡(luò)入侵者帶來了方便。因此,未來的計算機(jī)網(wǎng)絡(luò)應(yīng)該具有很高的安全性和可靠性,可以抵御高智商的網(wǎng)絡(luò)入侵者,使用戶更加可靠、更加方便地?fù)碛写罅扛魇礁鳂拥膫€性化客戶服務(wù)。</p><p>  1.1 課程設(shè)計的目的</p><p> 

8、 本次設(shè)計的目的就是在掌握計算機(jī)網(wǎng)絡(luò)理論的基礎(chǔ)上,了解網(wǎng)絡(luò)技術(shù),掌握網(wǎng)絡(luò)相關(guān)設(shè)計方法和思想,通過本次課程設(shè)計,達(dá)到鞏固和綜合運用計算機(jī)網(wǎng)絡(luò)原理的知識,理論聯(lián)系實際,鞏固所學(xué)理論知識,并且提高自己通過所學(xué)理論分析、解決計算機(jī)實際問題的能力。</p><p>  掌握計算機(jī)網(wǎng)絡(luò)課程的知識可使學(xué)生打下一個堅實的專業(yè)基礎(chǔ),可提高處理通信系統(tǒng)問題能力和素質(zhì)。由于通信工程專業(yè)理論深、實踐性強(qiáng),做好課程設(shè)計,對學(xué)生掌握本專業(yè)的

9、知識、提高其基本能力是非常重要的。 </p><p>  本次設(shè)計的目的也是為了學(xué)生加深對所學(xué)計算機(jī)網(wǎng)絡(luò)知識的理解,培養(yǎng)學(xué)生專業(yè)素質(zhì),提高利用計算機(jī)網(wǎng)絡(luò)知識處理通信系統(tǒng)問題的能力,為今后的專業(yè)課程的學(xué)習(xí)、畢業(yè)設(shè)計和工作打下良好的基礎(chǔ)。使學(xué)生能比較扎實地掌握本專業(yè)的基礎(chǔ)知識和基本理論。 </p><p>  本次課程設(shè)計主要是基于Linux系統(tǒng),使用編程語言C語言,編寫一個實驗程序,實現(xiàn)基于

10、ICMP報文的PING的類似功能。本文主要介紹了ICMP報文,PING功能的相關(guān)原理,根據(jù)設(shè)計要求,用C語言編程運行、仿真,通過觀察實驗結(jié)果,從而判定本次設(shè)計成功完成任務(wù)。通過這次計算機(jī)網(wǎng)絡(luò)方面的課程設(shè)計,提高了我們對網(wǎng)絡(luò)領(lǐng)域的認(rèn)識,有利于培養(yǎng)我們在該方面的設(shè)計能力。一人一題特別有利于鍛煉我們獨立分析問題和解決問題的能力。設(shè)計過程的復(fù)雜加老師的嚴(yán)格要求有益于培養(yǎng)我們嚴(yán)謹(jǐn)?shù)墓ぷ髯黠L(fēng)。</p><p>  1.2 課

11、程設(shè)計的主要任務(wù)和要求</p><p><b>  課程設(shè)計的主要任務(wù)</b></p><p>  編程實現(xiàn)PING的服務(wù)器端和客戶端,實現(xiàn)操作系統(tǒng)提供的ping命令的類似功能。</p><p>  服務(wù)器端PingServer功能:</p><p>  可以并發(fā)地為多個用戶服務(wù);</p><p>

12、;  顯示用戶通過客戶端發(fā)送來的消息內(nèi)容(包含頭部和payload);</p><p>  能夠模擬分組的丟失;能夠模擬分組傳輸延遲;</p><p>  將用戶發(fā)送來的請求request在延遲一段隨機(jī)選擇的時間(小于1s)后返回給客戶端,作為收到請求的響應(yīng)reply;</p><p>  通過如下命令行啟動服務(wù)器:java PingServer port。<

13、/p><p>  port為PingServer的工作端口號</p><p>  客戶端PingClient功能:</p><p>  啟動后發(fā)送10個request。發(fā)送一個request后,最多等待1秒以便接收PingServer返回的reply消息。如果在該時間內(nèi)沒有收到服務(wù)器的reply,則認(rèn)為該請求或?qū)υ撜埱蟮膔eply已經(jīng)丟失;在收到reply后立即發(fā)送下一

14、個request。</p><p>  請求消息的payload中至少包含關(guān)鍵字PingUDP、序號、時間戳等內(nèi)容。如:PingUDP SequenceNumber TimeStamp CRLF</p><p>  其中:CRLF表示回車換行符(0X0D0A);TimeStamp為發(fā)送該消息的機(jī)器時間。</p><p>  為每個請求計算折返時間(RTT),統(tǒng)計10

15、個請求的平均RTT、最大/小RTT。</p><p>  通過如下命令行啟動:java PingClient host port。host為PingServer所在的主機(jī)地址;port為PingServer的工作端口號</p><p><b>  課程設(shè)計的要求:</b></p><p> ?。?)按要求編寫課程設(shè)計報告書,能正確闡述設(shè)計結(jié)果。

16、</p><p> ?。?)通過課程設(shè)計培養(yǎng)學(xué)生嚴(yán)謹(jǐn)?shù)目茖W(xué)態(tài)度,認(rèn)真的工作作風(fēng)和團(tuán)隊協(xié)作精神。</p><p> ?。?)學(xué)會文獻(xiàn)檢索的基本方法和綜合運用文獻(xiàn)的能力。</p><p> ?。?)在老師的指導(dǎo)下,要求每個學(xué)生獨立完成課程設(shè)計的全部內(nèi)容。</p><p><b>  2 理論基礎(chǔ)</b></p>

17、<p>  2.1 ICMP相關(guān)介紹</p><p>  ICMP是(Internet Control Message Protocol)Internet控制報文協(xié)議。它是TCP/IP協(xié)議族的一個子協(xié)議,用于在IP主機(jī)、路由器之間傳遞控制消息??刂葡⑹侵妇W(wǎng)絡(luò)通不通、主機(jī)是否可達(dá)、路由是否可用等網(wǎng)絡(luò)本身的消息。這些控制消息雖然并不傳輸用戶數(shù)據(jù),但是對于用戶數(shù)據(jù)的傳遞起著重要的作用。</p>

18、<p>  ICMP協(xié)議是一種面向無連接的協(xié)議,用于傳輸出錯報告控制信息。它是一個非常重要的協(xié)議,它對于網(wǎng)絡(luò)安全具有極其重要的意義。 </p><p>  它是TCP/IP協(xié)議族的一個子協(xié)議,屬于網(wǎng)絡(luò)層協(xié)議,主要用于在主機(jī)與路由器之間傳遞控制信息,包括報告錯誤、交換受限控制和狀態(tài)信息等。當(dāng)遇到IP數(shù)據(jù)無法訪問目標(biāo)、IP路由器無法按當(dāng)前的傳輸速率轉(zhuǎn)發(fā)數(shù)據(jù)包等情況時,會自動發(fā)送ICMP消息。 </

19、p><p>  ICMP提供一致易懂的出錯報告信息。發(fā)送的出錯報文返回到發(fā)送原數(shù)據(jù)的設(shè)備,因為只有發(fā)送設(shè)備才是出錯報文的邏輯接受者。發(fā)送設(shè)備隨后可根據(jù)ICMP報文確定發(fā)生錯誤的類型,并確定如何才能更好地重發(fā)失敗的數(shù)據(jù)報。但是ICMP唯一的功能是報告問題而不是糾正錯誤,糾正錯誤的任務(wù)由發(fā)送方完成。 </p><p>  我們在網(wǎng)絡(luò)中經(jīng)常會使用到ICMP協(xié)議,比如我們經(jīng)常使用的用于檢查網(wǎng)絡(luò)通不通的

20、Ping命令(Linux和Windows中均有),這個“Ping”的過程實際上就是ICMP協(xié)議工作的過程。還有其他的網(wǎng)絡(luò)命令如跟蹤路由的Tracert命令也是基于ICMP協(xié)議的。</p><p>  ICMP協(xié)議對于網(wǎng)絡(luò)安全具有極其重要的意義。ICMP協(xié)議本身的特點決定了它非常容易被用于攻擊網(wǎng)絡(luò)上的路由器和主機(jī)。例如,在1999年8月海信集團(tuán)“懸賞”50萬元人民幣測試防火墻的過程中,其防火墻遭受到的ICMP攻擊達(dá)

21、334050次之多,占整個攻擊總數(shù)的90%以上!可見,ICMP的重要性絕不可以忽視! </p><p>  比如,可以利用操作系統(tǒng)規(guī)定的ICMP數(shù)據(jù)包最大尺寸不超過64KB這一規(guī)定,向主機(jī)發(fā)起“Ping of Death”(死亡之Ping)攻擊?!癙ing of Death” 攻擊的原理是:如果ICMP數(shù)據(jù)包的尺寸超過64KB上限時,主機(jī)就會出現(xiàn)內(nèi)存分配錯誤,導(dǎo)致TCP/IP堆棧崩潰,致使主機(jī)死機(jī)。(現(xiàn)在的操作系

22、統(tǒng)已經(jīng)取消了發(fā)送ICMP數(shù)據(jù)包的大小的限制,解決了這個漏洞) </p><p>  此外,向目標(biāo)主機(jī)長時間、連續(xù)、大量地發(fā)送ICMP數(shù)據(jù)包,也會最終使系統(tǒng)癱瘓。大量的ICMP數(shù)據(jù)包會形成“ICMP風(fēng)暴”,使得目標(biāo)主機(jī)耗費大量的CPU資源處理,疲于奔命。</p><p>  2.2 PING相關(guān)介紹</p><p>  Ping 是Windows系列自帶的一個可執(zhí)行

23、命令。利用它可以檢查網(wǎng)絡(luò)是否能夠連通,用好它可以很好地幫助我們分析判定網(wǎng)絡(luò)故障。應(yīng)用格式:Ping IP地址。該命令還可以加許多參數(shù)使用,PING是DOS命令,一般用于檢測網(wǎng)絡(luò)通與不通 ,也叫時延,其值越大,速度越慢。</p><p>  PING (Packet Internet Grope),因特網(wǎng)包探索器,用于測試網(wǎng)絡(luò)連接量的程序。Ping發(fā)送一個ICMP回聲請求消息給目的地并報告是否收到所希望的ICMP回

24、聲應(yīng)答。 </p><p>  它是用來檢查網(wǎng)絡(luò)是否通暢或者網(wǎng)絡(luò)連接速度的命令。作為一個生活在網(wǎng)絡(luò)上的管理員或者黑客來說,ping命令是第一個必須掌握的DOS命令,它所利用的原理是這樣的:利用網(wǎng)絡(luò)上機(jī)器IP地址的唯一性,給目標(biāo)IP地址發(fā)送一個數(shù)據(jù)包,再要求對方返回一個同樣大小的數(shù)據(jù)包來確定兩臺網(wǎng)絡(luò)機(jī)器是否連接相通,時延是多少? </p><p>  ping指的是端對端連通,通常用來作為可

25、用性的檢查, 但是某些病毒木馬會強(qiáng)行大量遠(yuǎn)程執(zhí)行ping命令搶占你的網(wǎng)絡(luò)資源,導(dǎo)致系統(tǒng)變慢,網(wǎng)速變慢。嚴(yán)禁ping入侵作為大多數(shù)防火墻的一個基本功能提供給用戶進(jìn)行選擇。通常的情況下你如果不用作服務(wù)器或者進(jìn)行網(wǎng)絡(luò)測試,可以放心的選中它,保護(hù)你的電腦。</p><p>  簡單的說,Ping就是一個測試程序,如果Ping運行正確,你大體上就可以排除網(wǎng)絡(luò)訪問層、網(wǎng)卡、MODEM的輸入輸出線路、電纜和路由器等存在的故障,

26、從而減小了問題的范圍。但由于可以自定義所發(fā)數(shù)據(jù)報的大小及無休止的高速發(fā)送,Ping也被某些別有用心的人作為DDOS(拒絕服務(wù)攻擊)的工具,曾經(jīng)Yahoo就是被黑客利用數(shù)百臺可以高速接入互聯(lián)網(wǎng)的電腦連續(xù)發(fā)送大量Ping數(shù)據(jù)包而癱瘓的。 </p><p> ?。牐牥凑杖笔≡O(shè)置,Windows上運行的Ping命令發(fā)送4個ICMP(網(wǎng)間控制報文協(xié)議)回送請求,每個32字節(jié)數(shù)據(jù),如果一切正常,你應(yīng)能得到4個回送應(yīng)答。 &l

27、t;/p><p>  Ping能夠以毫秒為單位顯示發(fā)送回送請求到返回回送應(yīng)答之間的時間量。如果應(yīng)答時間短,表示數(shù)據(jù)報不必通過太多的路由器或網(wǎng)絡(luò)連接速度比較快。Ping還能顯示TTL(Time To Live存在時間)值,你可以通過TTL值推算一下數(shù)據(jù)包已經(jīng)通過了多少個路由器:源地點TTL起始值(就是比返回TTL略大的一個2的乘方數(shù))-返回時TTL值。例如,返回TTL值為119,那么可以推算數(shù)據(jù)報離開源地址的TTL起始

28、值為128,而源地點到目標(biāo)地點要通過9個路由器網(wǎng)段(128-119);如果返回TTL值為246,TTL起始值就是256,源地點到目標(biāo)地點要通過9個路由器網(wǎng)段。 </p><p>  通過Ping檢測網(wǎng)絡(luò)故障的典型次序。</p><p> ?。牐犝G闆r下,當(dāng)你使用Ping命令來查找問題所在或檢驗網(wǎng)絡(luò)運行情況時,你需要使用許多Ping命令,如果所有都運行正確,你就可以相信基本的連通性和配置參

29、數(shù)沒有問題;如果某些Ping命令出現(xiàn)運行故障,它也可以指明到何處去查找問題。下面就給出一個典型的檢測次序及對應(yīng)的可能故障: </p><p>  ping 127.0.0.1--這個Ping命令被送到本地計算機(jī)的IP軟件,該命令永不退出該計算機(jī)。如果沒有做到這一點,就表示TCP/IP的安裝或運行存在某些最基本的問題。 </p><p>  ping 本機(jī)IP--這個命令被送到你計算機(jī)所配置

30、的IP地址,你的計算機(jī)始終都應(yīng)該對該Ping命令作出應(yīng)答,如果沒有,則表示本地配置或安裝存在問題。出現(xiàn)此問題時,局域網(wǎng)用戶請斷開網(wǎng)絡(luò)電纜,然后重新發(fā)送該命令。如果網(wǎng)線斷開后本命令正確,則表示另一臺計算機(jī)可能配置了相同的IP地址。 </p><p>  ping 局域網(wǎng)內(nèi)其他IP--這個命令應(yīng)該離開你的計算機(jī),經(jīng)過網(wǎng)卡及網(wǎng)絡(luò)電纜到達(dá)其他計算機(jī),再返回。收到回送應(yīng)答表明本地網(wǎng)絡(luò)中的網(wǎng)卡和載體運行正確。但如果收到0個回

31、送應(yīng)答,那么表示子網(wǎng)掩碼(進(jìn)行子網(wǎng)分割時,將IP地址的網(wǎng)絡(luò)部分與主機(jī)部分分開的代碼)不正確或網(wǎng)卡配置錯誤或電纜系統(tǒng)有問題。 </p><p>  ping 網(wǎng)關(guān)IP--這個命令如果應(yīng)答正確,表示局域網(wǎng)中的網(wǎng)關(guān)路由器正在運行并能夠作出應(yīng)答。</p><p>  3 結(jié)構(gòu)定義與程序設(shè)計</p><p>  3.1 IP首部結(jié)構(gòu)與程序定義</p><p

32、>  由于IP層協(xié)議是一種點對點的協(xié)議,而非端對端的協(xié)議,它提供無連接的數(shù)據(jù)報服務(wù),沒有端口的概念,因此很少使用bind()和connect()函數(shù),若有使用也只是用于設(shè)置IP地址。發(fā)送數(shù)據(jù)使用sendto()函數(shù),接收數(shù)據(jù)使用recvfrom()函數(shù)。IP報頭格式如圖3-1所示:</p><p>  圖3-1 IP報頭格式</p><p>  在Linux中,IP報頭格式數(shù)據(jù)結(jié)構(gòu)(

33、<netinet/ip.h>)定義如下:</p><p><b>  struct ip</b></p><p><b>  {</b></p><p>  #if __BYTE_ORDER == __LITTLE_ENDIAN</p><p>  unsigned int ip_hl:

34、4; /* header length */</p><p>  unsigned int ip_v:4; /* version */</p><p><b>  #endif</b></p><p>  #if __BYTE_ORDER == __BIG_ENDIAN</p&

35、gt;<p>  unsigned int ip_v:4; /* version */</p><p>  unsigned int ip_hl:4; /* header length */</p><p><b>  #endif</b></p><p>  u_int8

36、_t ip_tos; /* type of service */</p><p>  u_short ip_len; /* total length */ </p><p>  u_short ip_id; /* identification */</p>

37、<p>  u_short ip_off; /* fragment offset field */</p><p>  #define IP_RF 0x8000 /* reserved fragment flag */</p><p>  #define IP_DF 0x4000

38、/* dont fragment flag */</p><p>  #define IP_MF 0x2000 /* more fragments flag */</p><p>  #define IP_OFFMASK 0x1fff /* mask for fragmenting bits */</p><p>  

39、u_int8_t ip_ttl; /* time to live */</p><p>  u_int8_t ip_p; /* protocol */</p><p>  u_short ip_sum; /* checksum */</p><p>  struct in

40、_addr ip_src, ip_dst; /* source and dest address */</p><p><b>  };</b></p><p>  其中ping程序只使用以下數(shù)據(jù): </p><p>  IP報頭長度IHL(Internet Header Length)以4字節(jié)為一個單位來記錄IP報頭的長度,是上述I

41、P數(shù)據(jù)結(jié)構(gòu)的ip_hl變量。 生存時間TTL(Time To Live)以秒為單位,指出IP數(shù)據(jù)報能在網(wǎng)絡(luò)上停留的最長時間,其值由發(fā)送方設(shè)定,并在經(jīng)過路由的每一個節(jié)點時減一,當(dāng)該值為0時,數(shù)據(jù)報將被丟棄,是上述IP數(shù)據(jù)結(jié)構(gòu)的ip_ttl變量。 </p><p>  3.2 ICMP首部結(jié)構(gòu)與程序定義</p><p>  ICMP報文分為兩種,一是錯誤報告報文,二是查詢報文。每個ICMP報

42、頭均包含類型、編碼和校驗和這三項內(nèi)容,長度為8位,8位和16位,其余選項則隨ICMP的功能不同而不同。</p><p>  Ping命令只使用眾多ICMP報文中的兩種:"請求回送'(ICMP_ECHO)和"請求回應(yīng)'(ICMP_ECHOREPLY)。在Linux中定義如下: </p><p>  #define ICMP_ECHO 0</p&g

43、t;<p>  #define ICMP_ECHOREPLY 8</p><p>  這兩種ICMP類型報頭格式如圖3-2所示:</p><p>  圖3-2 ICMP類型報頭格式</p><p>  在Linux中ICMP數(shù)據(jù)結(jié)構(gòu)(<netinet/ip_icmp.h>)定義如下:</p><p>  struc

44、t icmp</p><p><b>  {</b></p><p>  u_int8_t icmp_type; /* type of message, see below */</p><p>  u_int8_t icmp_code; /* type sub code */</p><p>  u_int16

45、_t icmp_cksum; /* ones complement checksum of struct */</p><p><b>  union</b></p><p><b>  {</b></p><p>  u_char ih_pptr; /* ICMP_PARAMPROB */</p>

46、<p>  struct in_addr ih_gwaddr; /* gateway address */</p><p>  struct ih_idseq /* echo datagram */</p><p><b>  {</b></p><p>  u_int16_t icd_id;</p><

47、;p>  u_int16_t icd_seq;</p><p>  } ih_idseq;</p><p>  u_int32_t ih_void;</p><p>  /* ICMP_UNREACH_NEEDFRAG -- Path MTU Discovery (RFC1191) */</p><p>  struct ih_pmtu

48、</p><p><b>  {</b></p><p>  u_int16_t ipm_void;</p><p>  u_int16_t ipm_nextmtu;</p><p>  } ih_pmtu;</p><p>  struct ih_rtradv</p><p&

49、gt;<b>  {</b></p><p>  u_int8_t irt_num_addrs; </p><p>  u_int8_t irt_wpa;</p><p>  u_int16_t irt_lifetime;</p><p>  } ih_rtradv;</p><p>  } ic

50、mp_hun;</p><p>  #define icmp_pptr icmp_hun.ih_pptr</p><p>  #define icmp_gwaddr icmp_hun.ih_gwaddr</p><p>  #define icmp_id icmp_hun.ih_idseq.icd_id</p><p>  #de

51、fine icmp_seq icmp_hun.ih_idseq.icd_seq</p><p>  #define icmp_void icmp_hun.ih_void</p><p>  #define icmp_pmvoid icmp_hun.ih_pmtu.ipm_void</p><p>  #define icmp_nextmtu

52、icmp_hun.ih_pmtu.ipm_nextmtu</p><p>  #define icmp_num_addrs icmp_hun.ih_rtradv.irt_num_addrs</p><p>  #define icmp_wpa icmp_hun.ih_rtradv.irt_wpa</p><p>  #define icmp_lifetime

53、 icmp_hun.ih_rtradv.irt_lifetime</p><p><b>  Union</b></p><p><b>  {</b></p><p><b>  struct</b></p><p><b>  {</b></

54、p><p>  u_int32_t its_otime;</p><p>  u_int32_t its_rtime;</p><p>  u_int32_t its_ttime;</p><p><b>  } id_ts;</b></p><p><b>  struct</b&g

55、t;</p><p><b>  {</b></p><p>  struct ip idi_ip;</p><p>  /* options and then 64 bits of data */</p><p><b>  } id_ip;</b></p><p>  s

56、truct icmp_ra_addr id_radv;</p><p>  u_int32_t id_mask;</p><p>  u_int8_t id_data[1];</p><p>  } icmp_dun;</p><p>  #define icmp_otime icmp_dun.id_ts.its_otime<

57、;/p><p>  #define icmp_rtime icmp_dun.id_ts.its_rtime</p><p>  #define icmp_ttime icmp_dun.id_ts.its_ttime</p><p>  #define icmp_ip icmp_dun.id_ip.idi_ip</p><p>  #d

58、efine icmp_radv icmp_dun.id_radv</p><p>  #define icmp_mask icmp_dun.id_mask</p><p>  #define icmp_data icmp_dun.id_data</p><p><b>  };</b></p><p>  使

59、用宏定義令表達(dá)更簡潔,其中ICMP報頭為8字節(jié),數(shù)據(jù)報長度最大為64K字節(jié)。 </p><p>  校驗和算法:這一算法稱為網(wǎng)際校驗和算法,把被校驗的數(shù)據(jù)16位進(jìn)行累加,然后取反碼,若數(shù)據(jù)字節(jié)長度為奇數(shù),則數(shù)據(jù)尾部補(bǔ)一個字節(jié)的0以湊成偶數(shù)。此算法適用于IPv4、ICMPv4、IGMPV4、ICMPv6、UDP和TCP校驗和,更詳細(xì)的信息請參考RFC1071,校驗和字段為上述ICMP數(shù)據(jù)結(jié)構(gòu)的icmp_cksum變

60、量。 </p><p>  標(biāo)識符:用于唯一標(biāo)識ICMP報文, 為上述ICMP數(shù)據(jù)結(jié)構(gòu)的icmp_id宏所指的變量。 </p><p>  順序號:ping命令的icmp_seq便由這里讀出,代表ICMP報文的發(fā)送順序,為上述ICMP數(shù)據(jù)結(jié)構(gòu)的icmp_seq宏所指的變量。 </p><p><b>  ICMP數(shù)據(jù)報</b></p>

61、;<p>  Ping命令中需要顯示的信息,包括icmp_seq和ttl都已有實現(xiàn)的辦法,但還缺rtt往返時間。為了實現(xiàn)這一功能,可利用ICMP數(shù)據(jù)報攜帶一個時間戳。使用以下函數(shù)生成時間戳:</p><p><b>  #include </b></p><p>  int gettimeofday(struct timeval *tp,void *tz

62、p)</p><p>  其中timeval結(jié)構(gòu)如下:</p><p>  struct timeval{</p><p>  long tv_sec;</p><p>  long tv_usec;</p><p><b>  }</b></p><p><b>

63、;  4 程序設(shè)計與驗證</b></p><p>  4.1 程序設(shè)計流程</p><p>  根據(jù)課程設(shè)計的要求,結(jié)合程序設(shè)計流程,本次設(shè)計按如下流程進(jìn)行,如圖4-1所示。</p><p><b>  Y</b></p><p><b>  N</b></p><p

64、>  圖4-1 程序設(shè)計流程圖</p><p>  4.2 程序驗證結(jié)果</p><p>  圖4-2 程序驗證截圖</p><p><b>  5 小結(jié)</b></p><p>  本次課程設(shè)計主要是基于Linux系統(tǒng),使用編程語言C語言,編寫一個實驗程序,實現(xiàn)基于ICMP報文的PING的類似功能。本文主要介紹

65、了ICMP報文,PING功能的相關(guān)原理,根據(jù)設(shè)計要求,用C語言編程運行、仿真,通過觀察實驗結(jié)果,從而判定本次設(shè)計成功完成任務(wù)。通過這次計算機(jī)網(wǎng)絡(luò)方面的課程設(shè)計,提高了我們對網(wǎng)絡(luò)領(lǐng)域的認(rèn)識,有利于培養(yǎng)我們在該方面的設(shè)計能力。一人一題特別有利于鍛煉我們獨立分析問題和解決問題的能力。設(shè)計過程的復(fù)雜加老師的嚴(yán)格要求有益于培養(yǎng)我們嚴(yán)謹(jǐn)?shù)墓ぷ髯黠L(fēng)</p><p>  在整個設(shè)計過程當(dāng)中,首先要根據(jù)模塊設(shè)計所要達(dá)到的要求編寫源

66、代碼,在編寫完后編譯的過程中經(jīng)常會出現(xiàn)程序編譯錯誤。根據(jù)系統(tǒng)提示,我找到了錯誤的位置,然后查詢錯誤的原因。通過和同學(xué)探討,或者請教老師,所有的問題都一一解決了。 </p><p>  在整個程序驗證執(zhí)行成功后發(fā)現(xiàn),其實整個設(shè)計實現(xiàn)的功能還是比較實用和易于操作的,而自己也為此付出了許多:從根據(jù)課題要求查找相關(guān)資料,學(xué)習(xí)編程語言,到自己能夠獨立編寫小

67、程序;從對Visual Studio2005軟件平臺的摸索,一次次修改程序,到仿真得到較滿意的結(jié)果;從對截圖工具的搜索下載,論文資料的搜集,到文字排版的學(xué)習(xí)。在設(shè)計過程中遇到了很多困難,在指導(dǎo)老師的指引和同學(xué)的幫助下,通過不斷探索學(xué)習(xí),使問題得到了一定的解決。終于使模擬PING功能正常運行,設(shè)計成功。</p><p>  通過本學(xué)期課程設(shè)計的學(xué)習(xí),我從中學(xué)習(xí)到了很多,對可編程邏輯器件,計算機(jī)編程語言,Visual

68、 Studio2005軟件平臺有了一定的了解,尤其是用C語言編程和仿真。在本次設(shè)計中最大的收獲是在不斷地發(fā)現(xiàn)問題,分析問題,解決問題的過程中培養(yǎng)了自己的科研能力,為今后的學(xué)習(xí)和工作積累了一定的經(jīng)驗。</p><p><b>  參考文獻(xiàn)</b></p><p>  [1]謝希仁.計算機(jī)網(wǎng)絡(luò)(第五版)[M].北京:電子工業(yè)出版社,2008</p><

69、p>  [2] (美)W.Richard Stevens. TCP/IP詳解·卷3:TCP 事務(wù)協(xié)議、HTTP、NNTP和UNIX域協(xié)議[M].北京:機(jī)械工業(yè)出版社,2000</p><p>  [3]李尊朝,蘇軍.Java語言程序設(shè)計(第二版)[M].北京:中國鐵道出版社,2008</p><p>  [4] 劉燁,用Java實現(xiàn)Socket模型. 科技信息(學(xué)術(shù)版)[J

70、],2007年,第32期:91</p><p>  附錄:源程序設(shè)計清單</p><p>  // 程序名稱:編程實現(xiàn)基于ICMP的PING</p><p>  // 程序功能:采用編程語言C語言設(shè)計程序,實現(xiàn)PING功能。</p><p>  // 程序作者:李明洪</p><p>  // 最后修改日期:2011-

71、7-1</p><p>  PING功能實現(xiàn)程序:</p><p>  #include <stdio.h></p><p>  #include <signal.h></p><p>  #include <arpa/inet.h></p><p>  #include <s

72、ys/types.h></p><p>  #include <sys/socket.h></p><p>  #include <unistd.h></p><p>  #include <netinet/in.h></p><p>  #include <netinet/ip.h>&l

73、t;/p><p>  #include <netinet/ip_icmp.h></p><p>  #include <netdb.h></p><p>  #include <setjmp.h></p><p>  #include <errno.h></p><p>  

74、#define PACKET_SIZE 4096</p><p>  #define MAX_WAIT_TIME 5</p><p>  #define MAX_NO_PACKETS 3</p><p>  char sendpacket[PACKET_SIZE];</p><p>  char recvpacket[PACKE

75、T_SIZE];</p><p>  int sockfd,datalen=56;</p><p>  int nsend=0,nreceived=0;</p><p>  struct sockaddr_in dest_addr;</p><p>  pid_t pid;</p><p>  struct socka

76、ddr_in from;</p><p>  struct timeval tvrecv;</p><p>  void statistics(int signo);</p><p>  unsigned short cal_chksum(unsigned short *addr,int len);</p><p>  int pack(in

77、t pack_no);</p><p>  void send_packet(void);</p><p>  void recv_packet(void);</p><p>  int unpack(char *buf,int len);</p><p>  void tv_sub(struct timeval *out,struct ti

78、meval *in);</p><p>  void statistics(int signo)</p><p>  { printf("\n--------------------PING statistics-------------------\n");</p><p>  printf("%d packets tra

79、nsmitted, %d received , %%%d lost\n",nsend,nreceived,</p><p>  (nsend-nreceived)/nsend*100);</p><p>  close(sockfd);</p><p><b>  exit(1);</b></p><p>&l

80、t;b>  }</b></p><p><b>  /*校驗和算法*/</b></p><p>  unsigned short cal_chksum(unsigned short *addr,int len)</p><p>  { int nleft=len;</p><p>  int

81、 sum=0;</p><p>  unsigned short *w=addr;</p><p>  unsigned short answer=0;</p><p>  /*把ICMP報頭二進(jìn)制數(shù)據(jù)以2字節(jié)為單位累加起來*/</p><p>  while(nleft>1)</p><p>  {

82、 sum+=*w++;</p><p><b>  nleft-=2;</b></p><p><b>  }</b></p><p>  /*若ICMP報頭為奇數(shù)個字節(jié),會剩下最后一字節(jié)。把最后一個字節(jié)視為一個2字節(jié)數(shù)據(jù)的高字節(jié),這個2字節(jié)數(shù)據(jù)的低字節(jié)為0,繼續(xù)累加*/</p><p>  if(

83、 nleft==1)</p><p>  { *(unsigned char *)(&answer)=*(unsigned char *)w;</p><p>  sum+=answer;</p><p><b>  }</b></p><p>  sum=(sum>>16)+(sum&a

84、mp;0xffff);</p><p>  sum+=(sum>>16);</p><p>  answer=~sum;</p><p>  return answer;</p><p><b>  }</b></p><p>  /*設(shè)置ICMP報頭*/</p><

85、;p>  int pack(int pack_no)</p><p>  { int i,packsize;</p><p>  struct icmp *icmp;</p><p>  struct timeval *tval;</p><p>  icmp=(struct icmp*)sendpacket;</p>&

86、lt;p>  icmp->icmp_type=ICMP_ECHO;</p><p>  icmp->icmp_code=0;</p><p>  icmp->icmp_cksum=0;</p><p>  icmp->icmp_seq=pack_no;</p><p>  icmp->icmp_id=pid

87、;</p><p>  packsize=8+datalen;</p><p>  tval= (struct timeval *)icmp->icmp_data;</p><p>  gettimeofday(tval,NULL); /*記錄發(fā)送時間*/</p><p>

88、;  icmp->icmp_cksum=cal_chksum( (unsigned short *)icmp,packsize); /*校驗算法*/</p><p>  return packsize;</p><p><b>  }</b></p><p>  /*發(fā)送三個ICMP報文*/</p><p>  v

89、oid send_packet()</p><p>  { int packetsize;</p><p>  while( nsend<MAX_NO_PACKETS)</p><p>  { nsend++;</p><p>  packetsize=pack(nsend); /*設(shè)置ICMP報頭*/</p><

90、;p>  if( sendto(sockfd,sendpacket,packetsize,0,</p><p>  (struct sockaddr *)&dest_addr,sizeof(dest_addr) )<0 )</p><p>  { perror("sendto error");</p><p>&

91、lt;b>  continue;</b></p><p><b>  }</b></p><p>  sleep(1); /*每隔一秒發(fā)送一個ICMP報文*/</p><p><b>  }</b></p><p>

92、;<b>  }</b></p><p>  /*接收所有ICMP報文*/</p><p>  void recv_packet()</p><p>  { int n,fromlen;</p><p>  extern int errno;</p><p>  signal(SIGALRM,st

93、atistics);</p><p>  fromlen=sizeof(from);</p><p>  while( nreceived<nsend)</p><p>  { alarm(MAX_WAIT_TIME);</p><p>  if( (n=recvfrom(sockfd,recvpacket,sizeof(recvpac

94、ket),0,</p><p>  (struct sockaddr *)&from,&fromlen)) <0)</p><p>  { if(errno==EINTR)continue;</p><p>  perror("recvfrom error");</p><p><b>  

95、continue;</b></p><p><b>  }</b></p><p>  gettimeofday(&tvrecv,NULL); /*記錄接收時間*/</p><p>  if(unpack(recvpacket,n)==-1)continue;</p><p

96、>  nreceived++;</p><p><b>  }</b></p><p><b>  }</b></p><p>  /*剝?nèi)CMP報頭*/</p><p>  int unpack(char *buf,int len)</p><p>  { int

97、i,iphdrlen;</p><p>  struct ip *ip;</p><p>  struct icmp *icmp;</p><p>  struct timeval *tvsend;</p><p>  double rtt;</p><p>  ip=(struct ip *)buf;</p&g

98、t;<p>  iphdrlen=ip->ip_hl<<2; /*求ip報頭長度,即ip報頭的長度標(biāo)志乘4*/</p><p>  icmp=(struct icmp *)(buf+iphdrlen); /*越過ip報頭,指向ICMP報頭*/</p><p>  len-=iphdrlen; /

99、*ICMP報頭及ICMP數(shù)據(jù)報的總長度*/</p><p>  if( len<8) /*小于ICMP報頭長度則不合理*/</p><p>  { printf("ICMP packets\'s length is less than 8\n");</p><p>  ret

100、urn -1;</p><p><b>  }</b></p><p>  /*確保所接收的是我所發(fā)的的ICMP的回應(yīng)*/</p><p>  if( (icmp->icmp_type==ICMP_ECHOREPLY) && (icmp->icmp_id==pid) )</p><p>  {

101、 tvsend=(struct timeval *)icmp->icmp_data;</p><p>  tv_sub(&tvrecv,tvsend); /*接收和發(fā)送的時間差*/</p><p>  rtt=tvrecv.tv_sec*1000+tvrecv.tv_usec/1000; /*以毫秒為單位計算rtt*/<

102、/p><p>  /*顯示相關(guān)信息*/</p><p>  printf("%d byte from %s: icmp_seq=%u ttl=%d rtt=%.3f ms\n",</p><p><b>  len,</b></p><p>  inet_ntoa(from.sin_addr),</

103、p><p>  icmp->icmp_seq,</p><p>  ip->ip_ttl,</p><p><b>  rtt);</b></p><p><b>  }</b></p><p>  else return -1;</p><

104、p><b>  }</b></p><p>  main(int argc,char *argv[])</p><p>  { struct hostent *host;</p><p>  struct protoent *protocol;</p><p>  unsigned long inaddr=0l;&

105、lt;/p><p>  int waittime=MAX_WAIT_TIME;</p><p>  int size=50*1024;</p><p>  if(argc<2)</p><p>  { printf("usage:%s hostname/IP address\n",argv[0]);</

106、p><p><b>  exit(1);</b></p><p><b>  }</b></p><p>  if( (protocol=getprotobyname("icmp") )==NULL)</p><p>  { perror("getprotoby

107、name");</p><p><b>  exit(1);</b></p><p><b>  }</b></p><p>  /*生成使用ICMP的原始套接字,這種套接字只有root才能生成*/</p><p>  if( (sockfd=socket(AF_INET,SOCK_RAW

108、,protocol->p_proto) )<0)</p><p>  { perror("socket error");</p><p><b>  exit(1);</b></p><p><b>  }</b></p><p>  /* 回收root權(quán)

109、限,設(shè)置當(dāng)前用戶權(quán)限*/</p><p>  setuid(getuid());</p><p>  /*擴(kuò)大套接字接收緩沖區(qū)到50K這樣做主要為了減小接收緩沖區(qū)溢出的的可能性,若無意中ping一個廣播地址或多播地址,將會引來大量應(yīng)答*/</p><p>  setsockopt(sockfd,SOL_SOCKET,SO_RCVBUF,&size,sizeo

110、f(size) );</p><p>  bzero(&dest_addr,sizeof(dest_addr));</p><p>  dest_addr.sin_family=AF_INET;</p><p>  /*判斷是主機(jī)名還是ip地址*/</p><p>  if( inaddr=inet_addr(argv[1])==IN

111、ADDR_NONE)</p><p>  { if((host=gethostbyname(argv[1]) )==NULL) /*是主機(jī)名*/</p><p>  { perror("gethostbyname error");</p><p><b>  exit(1);</b></p>

112、;<p><b>  }</b></p><p>  memcpy( (char *)&dest_addr.sin_addr,host->h_addr,host->h_length);</p><p><b>  }</b></p><p>  else

113、 /*是ip地址*/</p><p>  memcpy( (char *)&dest_addr,(char *)&inaddr,host->h_length);</p><p>  /*獲取main的進(jìn)程id,用于設(shè)置ICMP的標(biāo)志符*/</p><p>  pid=getpid();</p>

114、;<p>  printf("PING %s(%s): %d bytes data in ICMP packets.\n",argv[1],</p><p>  inet_ntoa(dest_addr.sin_addr),datalen);</p><p>  send_packet(); /*發(fā)送

115、所有ICMP報文*/</p><p>  recv_packet(); /*接收所有ICMP報文*/</p><p>  statistics(SIGALRM); /*進(jìn)行統(tǒng)計*/</p><p><b>  return 0;</b></p><p><b

116、>  }</b></p><p>  /*兩個timeval結(jié)構(gòu)相減*/</p><p>  void tv_sub(struct timeval *out,struct timeval *in)</p><p>  { if( (out->tv_usec-=in->tv_usec)<0)</p><

117、;p>  { --out->tv_sec;</p><p>  out->tv_usec+=1000000;</p><p><b>  }</b></p><p>  out->tv_sec-=in->tv_sec;</p><p><b>  }</b>

溫馨提示

  • 1. 本站所有資源如無特殊說明,都需要本地電腦安裝OFFICE2007和PDF閱讀器。圖紙軟件為CAD,CAXA,PROE,UG,SolidWorks等.壓縮文件請下載最新的WinRAR軟件解壓。
  • 2. 本站的文檔不包含任何第三方提供的附件圖紙等,如果需要附件,請聯(lián)系上傳者。文件的所有權(quán)益歸上傳用戶所有。
  • 3. 本站RAR壓縮包中若帶圖紙,網(wǎng)頁內(nèi)容里面會有圖紙預(yù)覽,若沒有圖紙預(yù)覽就沒有圖紙。
  • 4. 未經(jīng)權(quán)益所有人同意不得將文件中的內(nèi)容挪作商業(yè)或盈利用途。
  • 5. 眾賞文庫僅提供信息存儲空間,僅對用戶上傳內(nèi)容的表現(xiàn)方式做保護(hù)處理,對用戶上傳分享的文檔內(nèi)容本身不做任何修改或編輯,并不能對任何下載內(nèi)容負(fù)責(zé)。
  • 6. 下載文件中如有侵權(quán)或不適當(dāng)內(nèi)容,請與我們聯(lián)系,我們立即糾正。
  • 7. 本站不保證下載資源的準(zhǔn)確性、安全性和完整性, 同時也不承擔(dān)用戶因使用這些下載資源對自己和他人造成任何形式的傷害或損失。

評論

0/150

提交評論