計(jì)算機(jī)網(wǎng)絡(luò)練習(xí)WireShark捕獲和分析數(shù)據(jù)包_第1頁
計(jì)算機(jī)網(wǎng)絡(luò)練習(xí)WireShark捕獲和分析數(shù)據(jù)包_第2頁
計(jì)算機(jī)網(wǎng)絡(luò)練習(xí)WireShark捕獲和分析數(shù)據(jù)包_第3頁
計(jì)算機(jī)網(wǎng)絡(luò)練習(xí)WireShark捕獲和分析數(shù)據(jù)包_第4頁
計(jì)算機(jī)網(wǎng)絡(luò)練習(xí)WireShark捕獲和分析數(shù)據(jù)包_第5頁
已閱讀5頁,還剩26頁未讀, 繼續(xù)免費(fèi)閱讀

下載本文檔

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

文檔簡介

1、計(jì)算機(jī)網(wǎng)絡(luò)練習(xí)之使用WireShark捕獲和分析數(shù)據(jù)包 Wireshark是世界上最流行的網(wǎng)絡(luò)分析工具。這個(gè)強(qiáng)大的工具可以捕捉網(wǎng)絡(luò)中的數(shù)據(jù),并為用戶提供關(guān)于網(wǎng)絡(luò)和上層協(xié)議的各種信息。與很多其他網(wǎng)絡(luò)工具一樣,Wireshark也使用pcap network library來進(jìn)行封包捕捉。視窗數(shù)據(jù)包捕獲(WinPcap的) :WinPcap的是Windows版本的libpcap庫,它包括一個(gè)驅(qū)動程序以支持捕獲數(shù)據(jù)包。Wireshark的使用這個(gè)庫來捕獲Windows Live網(wǎng)絡(luò)上的數(shù)據(jù).Wireshark的優(yōu)勢:- 安裝方便。- 簡單易用的界面。- 提供豐富的功能。一:安裝并運(yùn)行wireshar

2、k開始捕獲數(shù)據(jù)包,如圖所示點(diǎn)擊第二行的start開始捕獲數(shù)據(jù)包。二:幾分鐘后就捕獲到許多的數(shù)據(jù)包了,主界面如圖所示: HYPERLINK /showpic.html l blogid=5d1ea6740100bp8q&url=/orignal/5d1ea67445e13f7fa4fb3 t _blank 如上圖所示,可看到很多捕獲的數(shù)據(jù)。第一列是捕獲數(shù)據(jù)的編號;第二列是捕獲數(shù)據(jù)的相對時(shí)間,從開始捕獲算為0.000秒;第三列是源地址,第四列是目的地址;第五列是數(shù)據(jù)包的信息。選中第一個(gè)數(shù)據(jù)幀,然后從整體上看看Wireshark的窗口,主要被分成三部分。上面部分是所有數(shù)據(jù)幀的列表;中間部分是數(shù)據(jù)幀的

3、描述信息;下面部分是幀里面的數(shù)據(jù)。簡單的使用打開軟件,選擇:capture-options,在 interface 中選擇一個(gè)網(wǎng)卡,并且在 capture -capturefilters 中增加一個(gè)過濾器,常用的過濾器如 ip.addr = 然后點(diǎn)capture- start ,就開始抓包了。要停止的話capture-stop,當(dāng)然也可以用上面的圖標(biāo)。抓到了包之后,是二進(jìn)制的,在包上面點(diǎn)擊右鍵選擇 Follow TCP Stream ,就可以看到 http 包了。幀號 時(shí)間 源地址 目的地址 高層協(xié)議 包內(nèi)信息概況No. Time Source Destination Protocol Inf

4、o1 0.000000 25 2 TCP 2764 http SYN Seq=0 Len=0 MSS=1460 源端口目的端口請求建立TCP鏈接以下為物理層的數(shù)據(jù)幀概況Frame 1 (62 bytes on wire, 62 bytes captured)1號幀,線路62字節(jié),實(shí)際捕獲62字節(jié)Arrival Time: Jan 21, 2008 15:17:33.910261000 捕獲日期和時(shí)間Time delta from previous packet:0.00000 seconds此包與前一包的時(shí)間間隔Time since reference or first frame: 0.00

5、 seconds此包與第1幀的間隔時(shí)間Frame Number: 1 幀序號Packet Length: 62 bytes 幀長度Capture Length: 62 bytes 捕獲長度Frame is marked: False 此幀是否做了標(biāo)記:否Protocols in frame: eth:ip:tcp 幀內(nèi)封裝的協(xié)議層次結(jié)構(gòu)Coloring Rule Name: HTTP 用不同顏色染色標(biāo)記的協(xié)議名稱:HTTPColoring Rule String: http | tcp.port = 80染色顯示規(guī)則的字符串:以下為數(shù)據(jù)鏈路層以太網(wǎng)幀頭部信息Ethernet II, Src:

6、AcerTech_5b:d4:61 (00:00:e2:5b:d4:61), Dst: Jetcell_e5:1d:0a (00:d0:2b:e5:1d:0a)以太網(wǎng)協(xié)議版本II,源地址:廠名_序號(網(wǎng)卡地址),目的:廠名_序號(網(wǎng)卡地址)Destination: Jetcell_e5:1d:0a (00:d0:2b:e5:1d:0a) 目的:廠名_序號(網(wǎng)卡地址) Source: AcerTech_5b:d4:61 (00:00:e2:5b:d4:61) 源:廠名_序號(網(wǎng)卡地址)Type: IP (0 x0800)幀內(nèi)封裝的上層協(xié)議類型為IP(十六進(jìn)制碼0800)以下為互聯(lián)網(wǎng)層IP包頭部信

7、息Internet Protocol, Src: 25 (25), Dst: 2 (2) 互聯(lián)網(wǎng)協(xié)議,源IP地址,目的IP地址Version: 4互聯(lián)網(wǎng)協(xié)議IPv4(此部分參看教材頁圖 122 的IPv4數(shù)據(jù)報(bào)字段結(jié)構(gòu))Header length: 20 bytes IP包頭部長度Differentiated Services Field:0 x00(DSCP 0 x00:Default;ECN:0 x00)差分服務(wù)字段Total Length: 48IP包的總長度Identification:0 x8360 (33632) 標(biāo)志字段Flags: 標(biāo)記字段(在路由傳輸時(shí),是否允許將此IP包分段

8、,教材頁)Fragment offset: 0分段偏移量(將一個(gè)IP包分段后傳輸時(shí),本段的標(biāo)識)Time to live: 128 生存期TTLProtocol: TCP (0 x06) 此包內(nèi)封裝的上層協(xié)議為TCPHeader checksum: 0 xe4ce correct 頭部數(shù)據(jù)的校驗(yàn)和Source: 25 (25) 源IP地址Destination: 2 (2)目的IP地址以下為傳輸層TCP數(shù)據(jù)段頭部信息Transmission Control Protocol, Src Port: 2764 (2764), Dst Port: http (80), Seq: 0, Len: 0

9、傳輸控制協(xié)議TCP的內(nèi)容Source port: 2764 (2764)源端口名稱(端口號)(此部分參看教材149頁圖5.7)Destination port: http (80) 目的端口名http(端口號80)Sequence number: 0 (relative sequence number) 序列號(相對序列號)Header length: 28 bytes 頭部長度Flags: 0 x02 (SYN) TCP標(biāo)記字段(本字段是SYN,是請求建立TCP連接)Window size: 65535 流量控制的窗口大小Checksum: 0 xf73b correct TCP數(shù)據(jù)段的校驗(yàn)

10、和Options: (8 bytes) 可選項(xiàng)三:開始分析數(shù)據(jù)在下圖中Filter后面的編輯框中輸入:arp(注意是小寫),然后回車或者點(diǎn)擊“Apply”按鈕現(xiàn)在只有ARP協(xié)議了,其他的協(xié)議數(shù)據(jù)包都被過濾掉了。注意到中間部分的三行前面都有一個(gè)“+”,點(diǎn)擊它,這一行就會被展開。如下圖所示:現(xiàn)在展開第一行??吹降慕Y(jié)果如下:在上圖中我們看到這個(gè)幀的一些基本信息:幀的編號:15(捕獲時(shí)的編號)幀的大小:60字節(jié)。再加上四個(gè)字節(jié)的CRC計(jì)算在里面,就剛好滿足最小64字節(jié)的要求。幀被捕獲的日期和時(shí)間:Dec 2,2008幀距離前一個(gè)幀的捕獲時(shí)間差:0.136438000幀距離第一個(gè)幀的捕獲時(shí)間差:4.70

11、4371000幀裝載的協(xié)議:ARP現(xiàn)在展開第二行:我們可以看到:目的地址(Destination):ff:ff:ff:ff:ff:ff (這是個(gè)MAC地址,這個(gè)MAC地址是一個(gè)廣播地址,就是局域網(wǎng)中的所有計(jì)算機(jī)都會接收這個(gè)數(shù)據(jù)幀)源地址(Source):Elitegro_2d:e7:db (00:0d:87:2d:e7:db)幀中封裝的協(xié)議類型:0 x0806,這個(gè)是ARP協(xié)議的類型編號。Trailer:是協(xié)議中填充的數(shù)據(jù),為了保證幀最少有64字節(jié)。展開第三行:地址解析協(xié)議硬件類型:以太網(wǎng)協(xié)議類型:IP硬件大小:6協(xié)議大?。?發(fā)送方MAC地址發(fā)送方IP地址目的MAC地址目的IP地址巧用Wire

12、shark有效管理內(nèi)網(wǎng)身為企業(yè)網(wǎng)絡(luò)管理員必須能夠在第一時(shí)間發(fā)現(xiàn)網(wǎng)絡(luò)問題和安全隱患,普通的網(wǎng)絡(luò)診斷方法已經(jīng)不能夠滿足高級需求,通過ping法也只能夠解決簡單網(wǎng)絡(luò)故障,特別是網(wǎng)絡(luò)不穩(wěn)定一會斷一會通的情況是簡單方法無法排查的。這時(shí)就需要專業(yè)的網(wǎng)絡(luò)管理員使用專業(yè)的工具去解決,相信各位都聽說過sniffer這個(gè)網(wǎng)絡(luò)數(shù)據(jù)探測軟件,通過他可以對網(wǎng)絡(luò)的所有數(shù)據(jù)包進(jìn)行分析,發(fā)現(xiàn)故障根源。下面介紹另外一款網(wǎng)絡(luò)嗅探器Wireshark,他在各個(gè)方面的表現(xiàn)是其他sniffer類網(wǎng)絡(luò)嗅探器無法比擬的。圖4圖5由于沒有設(shè)置任何過濾信息和規(guī)則,所以Wireshark會對網(wǎng)絡(luò)中所有數(shù)據(jù)進(jìn)行檢測,從捕獲窗口可以看到各個(gè)不同協(xié)議

13、數(shù)據(jù)的數(shù)量和占據(jù)總數(shù)的百分比(如圖6)。圖6點(diǎn)“Stop”按鈕停止檢測后我們就可以針對每個(gè)網(wǎng)絡(luò)數(shù)據(jù)包進(jìn)行分析了,Wireshark會把剛剛捕獲的所有數(shù)據(jù)包羅列出來,如果數(shù)據(jù)內(nèi)容沒有加密的話也可以明文顯示出來。三、Wireshark應(yīng)用實(shí)例簡介Wireshark的初級使用還是非常簡單的,但是高級應(yīng)用和技巧就需要我們在日常工作中去積累和運(yùn)用了。下面簡單介紹三個(gè)小應(yīng)用,希望可以達(dá)到拋磚引玉的目的。(1)檢測網(wǎng)中是否有MSN或QQ在使用有的時(shí)候我們企業(yè)不希望員工在上班時(shí)通過MSN或QQ聊天,并針對這些IM交流軟件進(jìn)行了封鎖,但是封鎖和突破總是對立的,很多員工會找到代理工具或者其他方法來突破限制。不過不

14、管他采用何種方法都無法逃避Wireshark的火眼金睛。我們打開Wireshark并設(shè)置好監(jiān)控網(wǎng)卡,之后掃描網(wǎng)絡(luò)中的數(shù)據(jù),收集一段時(shí)間后停止捕獲來查看數(shù)據(jù)包,如果網(wǎng)絡(luò)中有MSN或者QQ在使用,Wireshark會記錄這些數(shù)據(jù)通話,在protocol協(xié)議處顯示為ICQ的通訊就是OICQ,而顯示為MSNMS的話則說明此數(shù)據(jù)包是MSN發(fā)送接收的,并且通過具體內(nèi)容我們還可以看到MSN的通話對象的郵件地址(如圖7)。圖7(2)按需捕獲制訂掃描規(guī)則可能會遇到捕獲后發(fā)現(xiàn)的數(shù)據(jù)包過多,無法分析的問題。實(shí)際上Wireshark容許我們制訂過濾規(guī)則,也就是說讓W(xué)ireshark只捕獲我們感興趣的數(shù)據(jù)包。具體方法是

15、在主界面選擇“Capture(捕獲)-Capture filter(捕獲規(guī)則)”,然后根據(jù)系統(tǒng)自帶的過濾規(guī)則或者自己研究他的規(guī)則語句來指定適合自己的捕獲規(guī)則(如圖8)。圖8這里假設(shè)我們只希望針對ARP數(shù)據(jù)包來檢測,來查看網(wǎng)絡(luò)中是否有ARP病毒的存在,首先需要我們設(shè)置ARP過濾規(guī)則,然后在捕獲窗口中的Capture filter處選擇制訂的過濾規(guī)則ARP,最后點(diǎn)“Start”開始掃描。這樣Wireshark將只針對ARP數(shù)據(jù)包進(jìn)行捕獲,其他數(shù)據(jù)包將不進(jìn)行任何記錄。具體捕獲詳細(xì)情況我們在捕獲窗口中可以一目了然(如圖9)。圖9(3)檢測明文數(shù)據(jù)包正如前面所說Wireshark可以針對網(wǎng)絡(luò)中的明文數(shù)據(jù)

16、包內(nèi)容進(jìn)行分析,例如我們在使用telnet來管理路由交換設(shè)備時(shí)所有的傳輸數(shù)據(jù)都是基于明文的,這樣通過Wireshark可以將telnet輸入的指令分析出來。首先檢測網(wǎng)絡(luò)數(shù)據(jù)包,如果在檢測過程中有人進(jìn)行telnet操作,那么在數(shù)據(jù)包顯示窗口中會看到對應(yīng)的telnet協(xié)議,以及通訊雙方的IP地址信息(如圖10)。圖10直接查看捕獲的每個(gè)telnet數(shù)據(jù)包中的DATA字段就可以看到明文字符了,這就是用戶telnet時(shí)輸入的信息(如圖11)。圖11Wireshark是功能強(qiáng)大的網(wǎng)絡(luò)數(shù)據(jù)捕獲工具,他可以幫助我們分析網(wǎng)絡(luò)數(shù)據(jù)流量,在第一時(shí)間發(fā)現(xiàn)蠕蟲病毒,木馬程序以及ARP欺騙等問題的根源。相信各位網(wǎng)絡(luò)管理

17、員一經(jīng)使用就會愛上他而離不開他。圖3 HYPERLINK /content/network/wireshark/Introduction.html /content/network/wireshark/Introduction.html本期向大家介紹了 Wireshark 的簡單原理,軟件特色, Wireshark 的安裝和使用設(shè)置。通過本期的介紹,大家已經(jīng)可以使用 Wireshark 捕獲數(shù)據(jù)包了。在下期,我們將向大家介紹 Wireshark 最有特色并且強(qiáng)大的數(shù)據(jù)包過濾功能,通過過濾,從而有的放矢的得到我們希望得到的數(shù)據(jù)包.附錄資料:不需要的可以自行刪除C語言中如何獲取時(shí)間?精度如何?1

18、使用time_t time( time_t * timer ) 精確到秒2 使用clock_t clock() 得到的是CPU時(shí)間精確到1/CLOCKS_PER_SEC秒3 計(jì)算時(shí)間差使用double difftime( time_t timer1, time_t timer0 )4 使用DWORD GetTickCount() 精確到毫秒5 如果使用MFC的CTime類,可以用CTime:GetCurrentTime() 精確到秒6 要獲取高精度時(shí)間,可以使用BOOL QueryPerformanceFrequency(LARGE_INTEGER *lpFrequency)獲取系統(tǒng)的計(jì)數(shù)器的

19、頻率BOOL QueryPerformanceCounter(LARGE_INTEGER *lpPerformanceCount)獲取計(jì)數(shù)器的值然后用兩次計(jì)數(shù)器的差除以Frequency就得到時(shí)間。7 Multimedia Timer FunctionsThe following functions are used with multimedia timers.timeBeginPeriod/timeEndPeriod/timeGetDevCaps/timeGetSystemTime/*/用標(biāo)準(zhǔn)C實(shí)現(xiàn)獲取當(dāng)前系統(tǒng)時(shí)間的函數(shù)一.time()函數(shù)time(&rawtime)函數(shù)獲取當(dāng)前時(shí)間距19

20、70年1月1日的秒數(shù),以秒計(jì)數(shù)單位,存于rawtime 中。#include time.hvoid main ()time_t rawtime;struct tm * timeinfo;time ( &rawtime );timeinfo = localtime ( &rawtime );printf ( 007The current date/time is: %s, asctime (timeinfo) );exit(0);=#include - 必須的時(shí)間函數(shù)頭文件time_t - 時(shí)間類型(time.h 定義是typedef long time_t; 追根溯源,time_t是long)

21、struct tm - 時(shí)間結(jié)構(gòu),time.h 定義如下:int tm_sec;int tm_min;int tm_hour;int tm_mday;int tm_mon;int tm_year;int tm_wday;int tm_yday;int tm_isdst;time ( &rawtime ); - 獲取時(shí)間,以秒計(jì),從1970年1月一日起算,存于rawtimelocaltime ( &rawtime ); - 轉(zhuǎn)為當(dāng)?shù)貢r(shí)間,tm 時(shí)間結(jié)構(gòu)asctime ()- 轉(zhuǎn)為標(biāo)準(zhǔn)ASCII時(shí)間格式:星期 月 日 時(shí):分:秒 年-二.clock()函數(shù),用clock()函數(shù),得到系統(tǒng)啟動以后的

22、毫秒級時(shí)間,然后除以CLOCKS_PER_SEC,就可以換成“秒”,標(biāo)準(zhǔn)c函數(shù)。clock_t clock ( void );#includeclock_t t = clock();long sec = t / CLOCKS_PER_SEC;他是記錄時(shí)鐘周期的,實(shí)現(xiàn)看來不會很精確,需要試驗(yàn)驗(yàn)證;-三.gettime(&t); 據(jù)說tc2.0的time結(jié)構(gòu)含有毫秒信息#include#includeint main(void)struct time t;gettime(&t);printf(The current time is: -:d:d.dn,t.ti_hour, t.ti_min, t.

23、ti_sec, t.ti_hund);return 0;time 是一個(gè)結(jié)構(gòu)體, 其中成員函數(shù) ti_hund 是毫秒。-四.GetTickCount(),這個(gè)是windows里面常用來計(jì)算程序運(yùn)行時(shí)間的函數(shù);DWORD dwStart = GetTickCount();/這里運(yùn)行你的程序代碼DWORD dwEnd = GetTickCount();則(dwEnd-dwStart)就是你的程序運(yùn)行時(shí)間, 以毫秒為單位這個(gè)函數(shù)只精確到55ms,1個(gè)tick就是55ms。-五.timeGetTime()t,imeGetTime()基本等于GetTickCount(),但是精度更高DWORD dwS

24、tart = timeGetTime();/這里運(yùn)行你的程序代碼DWORD dwEnd = timeGetTime();則(dwEnd-dwStart)就是你的程序運(yùn)行時(shí)間, 以毫秒為單位雖然返回的值單位應(yīng)該是ms,但傳說精度只有10ms。=/*Unix#unix時(shí)間相關(guān),也是標(biāo)準(zhǔn)庫的/*1.timegm函數(shù)只是將struct tm結(jié)構(gòu)轉(zhuǎn)成time_t結(jié)構(gòu),不使用時(shí)區(qū)信息;time_t timegm(struct tm *tm);2.mktime使用時(shí)區(qū)信息time_t mktime(struct tm *tm);timelocal 函數(shù)是GNU擴(kuò)展的與posix函數(shù)mktime相當(dāng)time_

25、t timelocal (struct tm *tm);3.gmtime函數(shù)只是將time_t結(jié)構(gòu)轉(zhuǎn)成struct tm結(jié)構(gòu),不使用時(shí)區(qū)信息;struct tm * gmtime(const time_t *clock);4.localtime使用時(shí)區(qū)信息struct tm * localtime(const time_t *clock);1.time獲取時(shí)間,stime設(shè)置時(shí)間time_t t;t = time(&t);2.stime其參數(shù)應(yīng)該是GMT時(shí)間,根據(jù)本地時(shí)區(qū)設(shè)置為本地時(shí)間;int stime(time_t *tp)3.UTC=true 表示采用夏時(shí)制;4.文件的修改時(shí)間等信息全部

26、采用GMT時(shí)間存放,不同的系統(tǒng)在得到修改時(shí)間后通過localtime轉(zhuǎn)換成本地時(shí)間;5.設(shè)置時(shí)區(qū)推薦使用setup來設(shè)置;6.設(shè)置時(shí)區(qū)也可以先更變/etc/sysconfig/clock中的設(shè)置再將ln -fs /usr/share/zoneinfo/xxxx/xxx /etc/localtime 才能重效time_t只能表示68年的范圍,即mktime只能返回1970-2038這一段范圍的time_t看看你的系統(tǒng)是否有time_t64,它能表示更大的時(shí)間范圍/*windows#Window里面的一些不一樣的/*一.CTime () 類VC編程一般使用CTime類 獲得當(dāng)前日期和時(shí)間CTime

27、 t = GetCurrentTime();SYSTEMTIME 結(jié)構(gòu)包含毫秒信息typedef struct _SYSTEMTIME WORD wYear;WORD wMonth;WORD wDayOfWeek;WORD wDay;WORD wHour;WORD wMinute;WORD wSecond;WORD wMilliseconds; SYSTEMTIME, *PSYSTEMTIME;SYSTEMTIME t1;GetSystemTime(&t1)CTime curTime(t1);WORD ms = t1.wMilliseconds;SYSTEMTIME sysTm;:GetLoc

28、alTime(&sysTm);在time.h中的_strtime() /只能在windows中用char t11;_strtime(t);puts(t);/*獲得當(dāng)前日期和時(shí)間CTime tm=CTime:GetCurrentTime();CString str=tm.Format(%Y-%m-%d);在VC中,我們可以借助CTime時(shí)間類,獲取系統(tǒng)當(dāng)前日期,具體使用方法如下:CTime t = CTime:GetCurrentTime(); /獲取系統(tǒng)日期,存儲在t里面int d=t.GetDay(); /獲得當(dāng)前日期int y=t.GetYear(); /獲取當(dāng)前年份int m=t.Get

29、Month(); /獲取當(dāng)前月份int h=t.GetHour(); /獲取當(dāng)前為幾時(shí)int mm=t.GetMinute(); /獲取當(dāng)前分鐘int s=t.GetSecond(); /獲取當(dāng)前秒int w=t.GetDayOfWeek(); /獲取星期幾,注意1為星期天,7為星期六二.CTimeSpan類如果想計(jì)算兩段時(shí)間的差值,可以使用CTimeSpan類,具體使用方法如下:CTime t1( 1999, 3, 19, 22, 15, 0 );CTime t = CTime:GetCurrentTime();CTimeSpan span=t-t1; /計(jì)算當(dāng)前系統(tǒng)時(shí)間與時(shí)間t1的間隔in

30、t iDay=span.GetDays(); /獲取這段時(shí)間間隔共有多少天int iHour=span.GetTotalHours(); /獲取總共有多少小時(shí)int iMin=span.GetTotalMinutes();/獲取總共有多少分鐘int iSec=span.GetTotalSeconds();/獲取總共有多少秒-三._timeb()函數(shù)_timeb定義在SYSTIMEB.H,有四個(gè)fieldsdstflagmillitmtimetimezonevoid _ftime( struct _timeb *timeptr );struct _timeb timebuffer;_ftime(

31、 &timebuffer );取當(dāng)前時(shí)間:文檔講可以到ms,有人測試,好象只能到16ms!四.設(shè)置計(jì)時(shí)器定義TIMER ID#define TIMERID_JISUANFANGSHI 2在適當(dāng)?shù)牡胤皆O(shè)置時(shí)鐘,需要開始其作用的地方;SetTimer(TIMERID_JISUANFANGSHI,200,NULL);在不需要定時(shí)器的時(shí)候的時(shí)候銷毀掉時(shí)鐘KillTimer(TIMERID_JISUANFANGSHI);對應(yīng)VC程序的消息映射void CJisuan:OnTimer(UINT nIDEvent)switch(nIDEvent)-#如何設(shè)定當(dāng)前系統(tǒng)時(shí)間-windowsSYSTEMTIME

32、m_myLocalTime,*lpSystemTime;m_myLocalTime.wYear=2003;m_myLocalTime.wM;m_myLocalTime.wDay=1;m_myLocalTime.wHour=0;m_myLocalTime.wMinute=0;m_myLocalTime.wSec;m_myLocalTime.wMillisec;lpSystemTime=&m_myLocalTime;if( SetLocalTime(lpSystemTime) ) /此處換成 SetSystemTime( )也不行MessageBox(OK !);elseMessageBox(Er

33、ror !);SYSTEMTIME m_myLocalTime,*lpSystemTime;m_myLocalTime.wYear=2003;m_myLocalTime.wM;m_myLocalTime.wDay=1;lpSystemTime=&m_myLocalTime;if( SetDate(lpSystemTime) ) /此處換成 SetSystemTime( )也不行MessageBox(OK !);elseMessageBox(Error !);本文來自CSDN博客,轉(zhuǎn)載請標(biāo)明出處:HYPERLINK /khuang2008/archive/2008/12/09/3483274.a

34、spx/khuang2008/archive/2008/12/09/3483274.aspx一種制作微秒級精度定時(shí)器的方法當(dāng)使用定時(shí)器時(shí),在很多情況下只用到毫秒級的時(shí)間間隔,所以只需用到下面的兩種常用方式就滿足要求了。一是用SetTimer函數(shù)建立一個(gè)定時(shí)器后,在程序中通過處理由定時(shí)器發(fā)送到線程消息隊(duì)列中的WM_TIMER消息,而得到定時(shí)的效果(退出程序時(shí)別忘了調(diào)用和SetTimer配對使用的KillTimer函數(shù))。二是利用GetTickCount函數(shù)可以返回自計(jì)算機(jī)啟動后的時(shí)間,通過兩次調(diào)用GetTickCount函數(shù),然后控制它們的差值來取得定時(shí)效果,此方式跟第一種方式一樣,精度也是毫秒

35、級的。用這兩種方式取得的定時(shí)效果雖然在許多場合已經(jīng)滿足實(shí)際的要求,但由于它們的精度只有毫秒級的,而且在要求定時(shí)時(shí)間間隔小時(shí),實(shí)際定時(shí)誤差大。下面介紹一種能取得高精度定時(shí)的方法。在一些計(jì)算機(jī)硬件系統(tǒng)中,包含有高精度運(yùn)行計(jì)數(shù)器(high-resolution performance counter),利用它可以獲得高精度定時(shí)間隔,其精度與CPU的時(shí)鐘頻率有關(guān)。采用這種方法的步驟如下:1、首先調(diào)用QueryPerformanceFrequency函數(shù)取得高精度運(yùn)行計(jì)數(shù)器的頻率f。單位是每秒多少次(n/s),此數(shù)一般很大。2、在需要定時(shí)的代碼的兩端分別調(diào)用QueryPerformanceCounter

36、以取得高精度運(yùn)行計(jì)數(shù)器的數(shù)值n1,n2。兩次數(shù)值的差值通過f換算成時(shí)間間隔,t=(n2-n1)/f。下面舉一個(gè)例子來演示這種方法的使用及它的精確度。在VC 6.0 下用MFC建立一個(gè)對話框工程,取名為HightTimer.在對話框面板中控件的布局如下圖:其中包含兩個(gè)靜態(tài)文本框,兩個(gè)編輯框和兩個(gè)按紐。上面和下面位置的編輯框的ID分別為IDC_E_TEST和IDC_E_ACTUAL,通過MFC ClassWizard添加的成員變量也分別對應(yīng)為DWORD m_dwTest和DWORD m_dwAct. “退出”按紐的ID為IDOK,“開始測試”按紐ID為IDC_B_TEST,用MFC ClassWi

37、zard添加此按紐的單擊消息處理函數(shù)如下:void CHightTimerDlg:OnBTest()/ TODO: Add your control notification handler code hereUpdateData(TRUE); /取輸入的測試時(shí)間值到與編輯框相關(guān)聯(lián)的成員變量m_dwTest中LARGE_INTEGER frequence;if(!QueryPerformanceFrequency( &frequence) /取高精度運(yùn)行計(jì)數(shù)器的頻率,若硬件不支持則返回FALSEMessageBox(Your computer hardware doesnt support t

38、he high-resolution performance counter,Not Support, MB_ICONEXCLAMATION | MB_OK);LARGE_INTEGER test, ret;test.QuadPart = frequence.QuadPart * m_dwTest / 1000000; /通過頻率換算微秒數(shù)到對應(yīng)的數(shù)量(與CPU時(shí)鐘有關(guān)),1秒=1000000微秒ret = MySleep( test ); /調(diào)用此函數(shù)開始延時(shí),返回實(shí)際花銷的數(shù)量m_dwAct = (DWORD)(1000000 * ret.QuadPart / frequence.Quad

39、Part ); /換算到微秒數(shù)UpdateData(FALSE); /顯示到對話框面板其中上面調(diào)用的MySleep函數(shù)如下:LARGE_INTEGER CHightTimerDlg:MySleep(LARGE_INTEGER Interval)/ 功能:執(zhí)行實(shí)際的延時(shí)功能 / 參數(shù):Interval 參數(shù)為需要執(zhí)行的延時(shí)與時(shí)間有關(guān)的數(shù)量 / 返回值:返回此函數(shù)執(zhí)行后實(shí)際所用的時(shí)間有關(guān)的數(shù)量 / LARGE_INTEGER privious, current, Elapse;QueryPerformanceCounter( &privious );current = privious;while

40、( current.QuadPart - privious.QuadPart Interval.QuadPart )QueryPerformanceCounter( t );Elapse.QuadPart = current.QuadPart - privious.QuadPart;return Elapse;注:別忘了在頭文件中為此函數(shù)添加函數(shù)聲明。至此,可以編譯和執(zhí)行此工程了,結(jié)果如上圖所示。在本人所用的機(jī)上(奔騰366, 64M內(nèi)存)測試,當(dāng)測試時(shí)間超過3微秒時(shí),準(zhǔn)確度已經(jīng)非常高了,此時(shí)機(jī)器執(zhí)行本身延時(shí)函數(shù)代碼的時(shí)間對需要延時(shí)的時(shí)間影響很小了。上面的函數(shù)由于演示測試的需要,沒有在函數(shù)級封

41、裝,下面給出的函數(shù)基本上可以以全局函數(shù)的形式照搬到別的程序中。BOOL MySleep(DWORD dwInterval)/ 功能:執(zhí)行微秒級的延時(shí)功能 / 參數(shù):Interval 參數(shù)為需要的延時(shí)數(shù)(單位:微秒) / 返回值:若計(jì)算機(jī)硬件不支持此功能,返回FALSE,若函數(shù)執(zhí)行成功,返回TRUE / BOOL bNormal = TRUE;LARGE_INTEGER frequence, privious, current, interval;if(!QueryPerformanceFrequency( &frequence):MessageBox(NULL, Your computer h

42、ardware doesnt support the high-resolution performance counter,Not Support, MB_ICONEXCLAMATION | MB_OK); /或其它的提示信息return FALSE;interval.QuadPart = frequence.QuadPart * dwInterval / 1000000;bNormal = bNormal & QueryPerformanceCounter( &privious );current = privious;while( current.QuadPart - privious.

43、QuadPart interval.QuadPart )bNormal = bNormal & QueryPerformanceCounter( t );return bNormal;需要指出的是,由于在此函數(shù)中的代碼很多,機(jī)器在執(zhí)行這些代碼所花費(fèi)的時(shí)間也很長,所以在需要幾個(gè)微秒的延時(shí)時(shí),會影響精度。實(shí)際上,讀者在熟悉這種方法后,只要使用QueryPerformanceFrequency和QueryPerformanceCounter這兩個(gè)函數(shù)就能按實(shí)際需要寫出自己的延時(shí)代碼了。使用CPU時(shí)間戳進(jìn)行高精度計(jì)時(shí)對關(guān)注性能的程序開發(fā)人員而言,一個(gè)好的計(jì)時(shí)部件既是益友,也是良師。計(jì)時(shí)器既可以作為程序

44、組件幫助程序員精確的控制程序進(jìn)程,又是一件有力的調(diào)試武器,在有經(jīng)驗(yàn)的程序員手里可以盡快的確定程序的性能瓶頸,或者對不同的算法作出有說服力的性能比較。在Windows平臺下,常用的計(jì)時(shí)器有兩種,一種是timeGetTime多媒體計(jì)時(shí)器,它可以提供毫秒級的計(jì)時(shí)。但這個(gè)精度對很多應(yīng)用場合而言還是太粗糙了。另一種是QueryPerformanceCount計(jì)數(shù)器,隨系統(tǒng)的不同可以提供微秒級的計(jì)數(shù)。對于實(shí)時(shí)圖形處理、多媒體數(shù)據(jù)流處理、或者實(shí)時(shí)系統(tǒng)構(gòu)造的程序員,善用QueryPerformanceCount/QueryPerformanceFrequency是一項(xiàng)基本功。本文要介紹的,是另一種直接利用Pe

45、ntium CPU內(nèi)部時(shí)間戳進(jìn)行計(jì)時(shí)的高精度計(jì)時(shí)手段。以下討論主要得益于Windows圖形編程一書,第15頁17頁,有興趣的讀者可以直接參考該書。關(guān)于RDTSC指令的詳細(xì)討論,可以參考Intel產(chǎn)品手冊。本文僅僅作拋磚之用。在Intel Pentium以上級別的CPU中,有一個(gè)稱為“時(shí)間戳(Time Stamp)”的部件,它以64位無符號整型數(shù)的格式,記錄了自CPU上電以來所經(jīng)過的時(shí)鐘周期數(shù)。由于目前的CPU主頻都非常高,因此這個(gè)部件可以達(dá)到納秒級的計(jì)時(shí)精度。這個(gè)精確性是上述兩種方法所無法比擬的。在Pentium以上的CPU中,提供了一條機(jī)器指令RDTSC(Read Time Stamp Co

46、unter)來讀取這個(gè)時(shí)間戳的數(shù)字,并將其保存在EDX:EAX寄存器對中。由于EDX:EAX寄存器對恰好是Win32平臺下C+語言保存函數(shù)返回值的寄存器,所以我們可以把這條指令看成是一個(gè)普通的函數(shù)調(diào)用。像這樣:inline unsigned _int64 GetCycleCount() _asm RDTSC 但是不行,因?yàn)镽DTSC不被C+的內(nèi)嵌匯編器直接支持,所以我們要用_emit偽指令直接嵌入該指令的機(jī)器碼形式0X0F、0X31,如下:inline unsigned _int64 GetCycleCount() _asm _emit 0 x0F _asm _emit 0 x31 以后在需要

47、計(jì)數(shù)器的場合,可以像使用普通的Win32 API一樣,調(diào)用兩次GetCycleCount函數(shù),比較兩個(gè)返回值的差,像這樣: unsigned long t; t = (unsigned long)GetCycleCount(); /Do Something time-intensive . t -= (unsigned long)GetCycleCount(); Windows圖形編程第15頁編寫了一個(gè)類,把這個(gè)計(jì)數(shù)器封裝起來。有興趣的讀者可以去參考那個(gè)類的代碼。作者為了更精確的定時(shí),做了一點(diǎn)小小的改進(jìn),把執(zhí)行RDTSC指令的時(shí)間,通過連續(xù)兩次調(diào)用GetCycleCount函數(shù)計(jì)算出來并保存了

48、起來,以后每次計(jì)時(shí)結(jié)束后,都從實(shí)際得到的計(jì)數(shù)中減掉這一小段時(shí)間,以得到更準(zhǔn)確的計(jì)時(shí)數(shù)字。但我個(gè)人覺得這一點(diǎn)點(diǎn)改進(jìn)意義不大。在我的機(jī)器上實(shí)測,這條指令大概花掉了幾十到100多個(gè)周期,在Celeron 800MHz的機(jī)器上,這不過是十分之一微秒的時(shí)間。對大多數(shù)應(yīng)用來說,這點(diǎn)時(shí)間完全可以忽略不計(jì);而對那些確實(shí)要精確到納秒數(shù)量級的應(yīng)用來說,這個(gè)補(bǔ)償也過于粗糙了。 這個(gè)方法的優(yōu)點(diǎn)是: 1.高精度??梢灾苯舆_(dá)到納秒級的計(jì)時(shí)精度(在1GHz的CPU上每個(gè)時(shí)鐘周期就是一納秒),這是其他計(jì)時(shí)方法所難以企及的。 2.成本低。timeGetTime 函數(shù)需要鏈接多媒體庫winmm.lib,QueryPerforma

49、nce* 函數(shù)根據(jù)MSDN的說明,需要硬件的支持(雖然我還沒有見過不支持的機(jī)器)和KERNEL庫的支持,所以二者都只能在Windows平臺下使用(關(guān)于DOS平臺下的高精度計(jì)時(shí)問題,可以參考圖形程序開發(fā)人員指南,里面有關(guān)于控制定時(shí)器8253的詳細(xì)說明)。但RDTSC指令是一條CPU指令,凡是i386平臺下Pentium以上的機(jī)器均支持,甚至沒有平臺的限制(我相信i386版本UNIX和Linux下這個(gè)方法同樣適用,但沒有條件試驗(yàn)),而且函數(shù)調(diào)用的開銷是最小的。 3.具有和CPU主頻直接對應(yīng)的速率關(guān)系。一個(gè)計(jì)數(shù)相當(dāng)于1/(CPU主頻Hz數(shù))秒,這樣只要知道了CPU的主頻,可以直接計(jì)算出時(shí)間。這和QueryPerformanceCount不同,后者需要通過QueryPerformanceFrequency獲取當(dāng)前計(jì)數(shù)器每秒的計(jì)數(shù)次數(shù)才能換算成時(shí)間。 這個(gè)方法的缺點(diǎn)是: 1.現(xiàn)有的C/C+編譯器多數(shù)不直接支持使用RDTSC指令,需要用直接嵌入機(jī)器碼的方式編程,比較麻煩。 2.數(shù)據(jù)抖動比較厲害。其實(shí)對任何計(jì)量手段而言

溫馨提示

  • 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. 人人文庫網(wǎng)僅提供信息存儲空間,僅對用戶上傳內(nèi)容的表現(xiàn)方式做保護(hù)處理,對用戶上傳分享的文檔內(nèi)容本身不做任何修改或編輯,并不能對任何下載內(nèi)容負(fù)責(zé)。
  • 6. 下載文件中如有侵權(quán)或不適當(dāng)內(nèi)容,請與我們聯(lián)系,我們立即糾正。
  • 7. 本站不保證下載資源的準(zhǔn)確性、安全性和完整性, 同時(shí)也不承擔(dān)用戶因使用這些下載資源對自己和他人造成任何形式的傷害或損失。

評論

0/150

提交評論