c++ winpcap开发(3)
現(xiàn)在我們已經(jīng)看到如何獲得適配器來玩,讓我們開始真正的工作,打開適配器并捕獲一些流量。 我們將編寫一個(gè)程序,其中打印出一些關(guān)于流經(jīng)適配器的數(shù)據(jù)包的信息。
打開捕獲設(shè)備的功能是pcap_open()。參數(shù),snaplen,標(biāo)志和to_ms值得一些解釋。
snaplen指定要捕獲的數(shù)據(jù)包的部分。在某些操作系統(tǒng)(如xBSD和Win32)上,數(shù)據(jù)包驅(qū)動(dòng)程序可以配置為僅捕獲任何數(shù)據(jù)包的初始部分:這會(huì)減少要復(fù)制到應(yīng)用程序的數(shù)據(jù)量,從而提高捕獲效率。在這種情況下,我們使用的值65536高于我們可能遇到的最大MTU值。以這種方式,我們確保應(yīng)用程序?qū)⑹冀K收到整個(gè)數(shù)據(jù)包。
標(biāo)志:最重要的標(biāo)志是指示適配器是否將處于混雜模式的標(biāo)志。在正常操作中,適配器僅捕獲來自網(wǎng)絡(luò)的分發(fā)給它的分組; 因此,其他主機(jī)交換的數(shù)據(jù)包被忽略。相反,當(dāng)適配器處于混雜模式時(shí),它將捕獲所有數(shù)據(jù)包是否注定到它。這意味著在共享介質(zhì)(如非交換式以太網(wǎng))上,WinPcap將能夠捕獲其他主機(jī)的數(shù)據(jù)包。混雜模式是大多數(shù)捕獲應(yīng)用程序的默認(rèn)模式,因此我們?cè)谝韵率纠袉⒂盟?
to_ms指定讀取超時(shí)(以毫秒為單位)。即使沒有來自網(wǎng)絡(luò)的數(shù)據(jù)包,適配器上的讀取(例如,使用pcap_dispatch()或pcap_next_ex())將始終在to_ms毫秒之后返回。如果適配器處于統(tǒng)計(jì)模式,to_ms還會(huì)定義統(tǒng)計(jì)報(bào)告之間的間隔。將to_ms設(shè)置為0表示沒有超時(shí),如果沒有數(shù)據(jù)包到達(dá),則適配器上的讀取將永遠(yuǎn)不會(huì)返回。另一端的-1超時(shí)導(dǎo)致適配器上的讀取始終立即返回。 #include "pcap.h"/* prototype of the packet handler */ void packet_handler(u_char *param, const struct pcap_pkthdr *header, const u_char *pkt_data);int main() { pcap_if_t *alldevs; pcap_if_t *d; int inum; int i=0; pcap_t *adhandle; char errbuf[PCAP_ERRBUF_SIZE];/* Retrieve the device list on the local machine */if (pcap_findalldevs_ex(PCAP_SRC_IF_STRING, NULL, &alldevs, errbuf) == -1){fprintf(stderr,"Error in pcap_findalldevs: %s\n", errbuf);exit(1);}/* Print the list */for(d=alldevs; d; d=d->next){printf("%d. %s", ++i, d->name);if (d->description)printf(" (%s)\n", d->description);elseprintf(" (No description available)\n");}if(i==0){printf("\nNo interfaces found! Make sure WinPcap is installed.\n");return -1;}printf("Enter the interface number (1-%d):",i);scanf_s("%d", &inum);if(inum < 1 || inum > i){printf("\nInterface number out of range.\n");/* Free the device list */pcap_freealldevs(alldevs);return -1;}/* Jump to the selected adapter */for(d=alldevs, i=0; i< inum-1 ;d=d->next, i++);/* Open the device */if ( (adhandle= pcap_open(d->name, // name of the device65536, // portion of the packet to capture// 65536 guarantees that the whole packet will be captured on all the link layersPCAP_OPENFLAG_PROMISCUOUS, // promiscuous mode1000, // read timeoutNULL, // authentication on the remote machineerrbuf // error buffer) ) == NULL){fprintf(stderr,"\nUnable to open the adapter. %s is not supported by WinPcap\n", d->name);/* Free the device list */pcap_freealldevs(alldevs);return -1;}printf("\nlistening on %s...\n", d->description);/* At this point, we don't need any more the device list. Free it */pcap_freealldevs(alldevs);/* start the capture */pcap_loop(adhandle, 0, packet_handler, NULL);return 0; }/* Callback function invoked by libpcap for every incoming packet */ void packet_handler(u_char *param, const struct pcap_pkthdr *header, const u_char *pkt_data) {struct tm ltime;char timestr[16];time_t local_tv_sec;/** unused variables*/(VOID)(param);(VOID)(pkt_data);/* convert the timestamp to readable format */local_tv_sec = header->ts.tv_sec;localtime_s(<ime, &local_tv_sec);strftime( timestr, sizeof timestr, "%H:%M:%S", <ime);printf("%s,%.6d len:%d\n", timestr, header->ts.tv_usec, header->len);}
一旦適配器打開,捕獲可以用pcap_dispatch()或pcap_loop()啟動(dòng)。這兩個(gè)函數(shù)非常相似,不同之處在于pcap_ dispatch()返回(盡管不能保證)超時(shí)時(shí)pcap_loop()不會(huì)返回,直到cnt數(shù)據(jù)包被捕獲為止,因此它可以在利用不足的網(wǎng)絡(luò)。pcap_loop()足以用于此示例,而pcap_dispatch()通常用于更復(fù)雜的程序中。
這兩個(gè)函數(shù)都有一個(gè)回調(diào)參數(shù)packet_handler,指向一個(gè)將接收數(shù)據(jù)包的函數(shù)。該函數(shù)由libpcap為來自網(wǎng)絡(luò)的每個(gè)新數(shù)據(jù)包調(diào)用,并接收通用狀態(tài)(對(duì)應(yīng)于pcap_loop()和pcap_dispatch()的用戶參數(shù)),該報(bào)頭具有數(shù)據(jù)包的一些信息,如時(shí)間戳和長度,數(shù)據(jù)包的實(shí)際數(shù)據(jù)包括所有協(xié)議頭。請(qǐng)注意,幀CRC通常不存在,因?yàn)樵趲?yàn)證后由網(wǎng)絡(luò)適配器刪除它。還要注意,大多數(shù)適配器丟棄CRC錯(cuò)誤的數(shù)據(jù)包,因此WinPcap通常不能捕獲它們。
上述示例從pcap_pkthdr頭提取每個(gè)數(shù)據(jù)包的時(shí)間戳和長度,并將其打印在屏幕上。
請(qǐng)注意,使用pcap_loop()可能存在缺點(diǎn),主要涉及到數(shù)據(jù)包捕獲驅(qū)動(dòng)程序調(diào)用處理程序的事實(shí);?因此用戶應(yīng)用程序沒有直接的控制權(quán)。另一種方法(并且具有更多可讀程序)是使用pcap_next_ex()函數(shù),該函數(shù)在下一個(gè)示例中顯示(捕獲不帶回調(diào)的數(shù)據(jù)包)。
新人創(chuàng)作打卡挑戰(zhàn)賽發(fā)博客就能抽獎(jiǎng)!定制產(chǎn)品紅包拿不停!
總結(jié)
以上是生活随笔為你收集整理的c++ winpcap开发(3)的全部?jī)?nèi)容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: HDOJ 1285 确定比赛名次(拓扑排
- 下一篇: 关于索引的相关 day45