日韩性视频-久久久蜜桃-www中文字幕-在线中文字幕av-亚洲欧美一区二区三区四区-撸久久-香蕉视频一区-久久无码精品丰满人妻-国产高潮av-激情福利社-日韩av网址大全-国产精品久久999-日本五十路在线-性欧美在线-久久99精品波多结衣一区-男女午夜免费视频-黑人极品ⅴideos精品欧美棵-人人妻人人澡人人爽精品欧美一区-日韩一区在线看-欧美a级在线免费观看

歡迎訪問 生活随笔!

生活随笔

當(dāng)前位置: 首頁 > 编程资源 > 编程问答 >内容正文

编程问答

winPcap编程之打开适配器并捕获数据包(四 转)

發(fā)布時間:2023/12/18 编程问答 28 豆豆
生活随笔 收集整理的這篇文章主要介紹了 winPcap编程之打开适配器并捕获数据包(四 转) 小編覺得挺不錯的,現(xiàn)在分享給大家,幫大家做個參考.

在貼源碼之前先介紹一個將要用到的很重要的函數(shù)--pcap_open(),下面是pcap_open()在remote-ex.h中的聲明:

pcap_t *pcap_open(const char *source, int snaplen, int flags, int read_timeout, struct pcap_rmtauth *auth, char *errbuf);

第一個參數(shù)不用多說,它表示的是設(shè)備的名稱。在獲取適配器鏈表后,通過返回數(shù)據(jù)域name即可知道設(shè)備的名稱。

? ? ? 第二個參數(shù)制定要捕獲數(shù)據(jù)包中的哪些部分。技術(shù)文檔中介紹說,在一些操作系統(tǒng)中,驅(qū)動可以被配置成只捕獲數(shù)據(jù)包的初始化部分,它的好處就是可以減少應(yīng)用程序間復(fù)制數(shù)量的量,從而提高捕獲效率。下面將要給出的實例程序中設(shè)為65535。我們知道對于使用以太網(wǎng)的局域網(wǎng)來說,最大傳輸單元為1500字節(jié),那么設(shè)為65535則能保證收到完整的數(shù)據(jù)包。

? ? ? 第三個參數(shù)是最重要的一個值,它用來指示適配器是否需要設(shè)置成混雜模式,這里引用一下技術(shù)文檔中對設(shè)置混雜模式的說明:

一般情況下,適配器只接收發(fā)給它自己的數(shù)據(jù)包, 而那些在其他機器之間通訊的數(shù)據(jù)包,將會被丟棄。 相反,如果適配器是混雜模式,那么不管這個數(shù)據(jù)包是不是發(fā)給我的,我都會去捕獲。也就是說,我會去捕獲所有的數(shù)據(jù)包。 這意味著在一個共享媒介(比如總線型以太網(wǎng)),WinPcap能捕獲其他主機的所有的數(shù)據(jù)包。 大多數(shù)用于數(shù)據(jù)捕獲的應(yīng)用程序都會將適配器設(shè)置成混雜模式,所以,我們也會在下面的范例中,使用混雜模式。

? ? ? 它的意思就是說設(shè)置混雜模式可以捕獲到所有經(jīng)過適配器的數(shù)據(jù)包,不論是不是發(fā)給機器本身的。PCAP_OPENFLAG_PROMISCUOUS這個值就是設(shè)置成混雜模式的意思。

? ? ? 第四個參數(shù)表示的是讀取數(shù)據(jù)的超時時間,單位是毫秒。意思就是說會在read_timeout時間內(nèi)對適配器的讀取操作進(jìn)行響應(yīng),不管有沒有讀到數(shù)據(jù)。這里有兩個特殊的值需要說明一下,如果將時間設(shè)置為0意味著沒有超時,那么如果沒有數(shù)據(jù)到達(dá)的話,讀操作就永遠(yuǎn)不會返回;如果設(shè)置為-1則恰恰相反,不論有沒有讀到數(shù)據(jù)都會立即返回。

? ? ? 第五個參數(shù)之前提到過,它表示的是連接遠(yuǎn)程用戶的驗證信息,由于我們不需要連接到遠(yuǎn)程用戶,這里置為NULL。

? ? ? 第六個參數(shù)是錯誤信息緩沖,如果該函數(shù)在調(diào)用過程中出錯則會將出錯信息保存在緩沖中。

? ? ? 函數(shù)的返回值是一個pcap_t的指針類型,查看聲明處我們可以發(fā)現(xiàn)pcap_t實際上是pcap結(jié)構(gòu)體,而文檔上說明它是一個已打開的捕捉實例的描述符。這個結(jié)構(gòu)體對用戶來說是不透明的(我們查看pcap的聲明處是找不到的),它通過wpcap.dll提供的函數(shù),維護(hù)了它的內(nèi)容。

? ? ? 下面我們來看一下這個程序的代碼!

1 #include <stdio.h> 2 #include <stdlib.h> 3 #include <string.h> 4 #define HAVE_REMOTE 5 #include <pcap.h> 6 7 /* packet handler 函數(shù)原型 */ 8 void packet_handler(u_char *param, const struct pcap_pkthdr *header, const u_char *pkt_data); 9 10 int main() 11 { 12 pcap_if_t *alldevs; 13 pcap_if_t *d; 14 int inum; 15 int i=0; 16 pcap_t *adhandle; 17 char errbuf[PCAP_ERRBUF_SIZE]; 18 19 /* 獲取本機設(shè)備列表 */ 20 if (pcap_findalldevs_ex(PCAP_SRC_IF_STRING, NULL, &alldevs, errbuf) == -1) 21 { 22 fprintf(stderr,"Error in pcap_findalldevs: %s\n", errbuf); 23 exit(1); 24 } 25 26 /* 打印列表 */ 27 for(d=alldevs; d; d=d->next) 28 { 29 printf("%d. %s", ++i, d->name); 30 if (d->description) 31 printf(" (%s)\n", d->description); 32 else 33 printf(" (No description available)\n"); 34 } 35 36 if(i==0) 37 { 38 printf("\nNo interfaces found! Make sure WinPcap is installed.\n"); 39 return -1; 40 } 41 42 printf("Enter the interface number (1-%d):",i); 43 scanf("%d", &inum); 44 45 if(inum < 1 || inum > i) 46 { 47 printf("\nInterface number out of range.\n"); 48 /* 釋放設(shè)備列表 */ 49 pcap_freealldevs(alldevs); 50 return -1; 51 } 52 53 /* 跳轉(zhuǎn)到選中的適配器 */ 54 for(d=alldevs, i=0; i< inum-1 ; d=d->next, i++); 55 56 /* 打開設(shè)備 */ 57 if ( (adhandle= pcap_open(d->name, // 設(shè)備名 58 65535, // 65535保證能捕獲到不同數(shù)據(jù)鏈路層上的每個數(shù)據(jù)包的全部內(nèi)容 59 PCAP_OPENFLAG_PROMISCUOUS, // 混雜模式 60 1000, // 讀取超時時間 61 NULL, // 遠(yuǎn)程機器驗證 62 errbuf // 錯誤緩沖池 63 ) ) == NULL) 64 { 65 fprintf(stderr,"\nUnable to open the adapter. %s is not supported by WinPcap\n", d->name); 66 /* 釋放設(shè)備列表 */ 67 pcap_freealldevs(alldevs); 68 return -1; 69 } 70 71 printf("\nlistening on %s...\n", d->description); 72 73 /* 釋放設(shè)備列表 */ 74 pcap_freealldevs(alldevs); 75 76 /* 開始捕獲 */ 77 pcap_loop(adhandle, 0, packet_handler, NULL); 78 79 return 0; 80 } 81 82 83 /* 每次捕獲到數(shù)據(jù)包時,libpcap都會自動調(diào)用這個回調(diào)函數(shù) */ 84 void packet_handler(u_char *param, const struct pcap_pkthdr *header, const u_char *pkt_data) 85 { 86 struct tm *ltime; 87 char timestr[16]; 88 time_t local_tv_sec; 89 90 /* 將時間戳轉(zhuǎn)換成可識別的格式 */ 91 local_tv_sec = header->ts.tv_sec; 92 ltime=localtime(&local_tv_sec); 93 strftime( timestr, sizeof timestr, "%H:%M:%S", ltime); 94 95 printf("%s,%.6ld len:%d\n", timestr, header->ts.tv_usec, header->len); 96 97 }

?

? 引用一下文檔里面對于pcap_loop()函數(shù)的介紹:

Collect a group of packets.

pcap_loop()?is similar to?pcap_dispatch()?except it keeps reading packets until cnt packets are processed or an error occurs. It does not return when live read timeouts occur. Rather, specifying a non-zero read timeout to?pcap_open_live()?and then callingpcap_dispatch()?allows the reception and processing of any packets that arrive when the timeout occurs. A negative cnt causespcap_loop()?to loop forever (or at least until an error occurs). -1 is returned on an error; 0 is returned if cnt is exhausted; -2 is returned if the loop terminated due to a call to?pcap_breakloop()?before any packets were processed. If your application uses?pcap_breakloop(), make sure that you explicitly check for -1 and -2, rather than just checking for a return value < 0.

? ? ? 大致就是說pcap_loop()函數(shù)是用來捕獲一組數(shù)據(jù)分組的。pcap_loop()函數(shù)跟pcap_dispath()函數(shù)很類似,唯一不同之處就是pcap_loop()會一直讀數(shù)據(jù)直到cnt數(shù)據(jù)被處理或者出現(xiàn)錯誤。不論讀取時間是否超時它都不返回。當(dāng)然有一種特殊情況,就是在調(diào)用pcap_open_live()函數(shù)時指定非0的讀取超時時間,調(diào)用pcap_dispath()函數(shù)可以在超時發(fā)生時對讀到的數(shù)據(jù)進(jìn)行接收和處理。將cnt設(shè)為正數(shù)可以使pcap_loop()一直循環(huán)(或至少到錯誤發(fā)生之前)。返回-1則出錯;返回0則說明cnt被耗盡;返回-2則是由于在數(shù)據(jù)被處理之前調(diào)用pcap_breakloop()來中斷循環(huán)。如果你的應(yīng)用程序使用了pcap_breakloop()函數(shù),你需要對返回值-1和-2進(jìn)行詳細(xì)的檢查,而不是只檢查<0的情況。(如果翻譯有誤還請指正!!!)

? ? ? 文檔里說得很詳細(xì),看得也是一頭霧水,也不知道究竟在說些什么。簡單來講就是說,pcap_loop()只有當(dāng)cnt數(shù)據(jù)包被捕獲時才會返回,即它會在一小段時間內(nèi)阻塞網(wǎng)絡(luò)的利用。pcap_loop()函數(shù)的第三個參數(shù)很重要,它是一個回調(diào)函數(shù)的函數(shù)指針,即pcap_loop()函數(shù)返回時會自動調(diào)用這個回調(diào)函數(shù)。這個回調(diào)函數(shù)的參數(shù)類型是規(guī)定好的:

typedef void (*pcap_handler)(u_char *, const struct pcap_pkthdr *,
const u_char *);

? ? ? 這個程序當(dāng)中我們只用到了第二個參數(shù),將每一個數(shù)據(jù)包的時間戳和長度從它的首部當(dāng)中解析出來,并打印在屏幕上。細(xì)節(jié)的東西就不贅述了,看一下運行的結(jié)果:

?輸入6并按回車,開始捕獲數(shù)據(jù)并打印:

?

轉(zhuǎn)載于:https://www.cnblogs.com/gdayq/p/5866306.html

總結(jié)

以上是生活随笔為你收集整理的winPcap编程之打开适配器并捕获数据包(四 转)的全部內(nèi)容,希望文章能夠幫你解決所遇到的問題。

如果覺得生活随笔網(wǎng)站內(nèi)容還不錯,歡迎將生活随笔推薦給好友。