c++ winpcap开发(3)
生活随笔
收集整理的這篇文章主要介紹了
c++ winpcap开发(3)
小編覺得挺不錯的,現在分享給大家,幫大家做個參考.
打開適配器并捕獲數據包
現在我們已經看到如何獲得適配器來玩,讓我們開始真正的工作,打開適配器并捕獲一些流量。 我們將編寫一個程序,其中打印出一些關于流經適配器的數據包的信息。
打開捕獲設備的功能是pcap_open()。參數,snaplen,標志和to_ms值得一些解釋。
snaplen指定要捕獲的數據包的部分。在某些操作系統(如xBSD和Win32)上,數據包驅動程序可以配置為僅捕獲任何數據包的初始部分:這會減少要復制到應用程序的數據量,從而提高捕獲效率。在這種情況下,我們使用的值65536高于我們可能遇到的最大MTU值。以這種方式,我們確保應用程序將始終收到整個數據包。
標志:最重要的標志是指示適配器是否將處于混雜模式的標志。在正常操作中,適配器僅捕獲來自網絡的分發給它的分組; 因此,其他主機交換的數據包被忽略。相反,當適配器處于混雜模式時,它將捕獲所有數據包是否注定到它。這意味著在共享介質(如非交換式以太網)上,WinPcap將能夠捕獲其他主機的數據包。混雜模式是大多數捕獲應用程序的默認模式,因此我們在以下示例中啟用它。
to_ms指定讀取超時(以毫秒為單位)。即使沒有來自網絡的數據包,適配器上的讀取(例如,使用pcap_dispatch()或pcap_next_ex())將始終在to_ms毫秒之后返回。如果適配器處于統計模式,to_ms還會定義統計報告之間的間隔。將to_ms設置為0表示沒有超時,如果沒有數據包到達,則適配器上的讀取將永遠不會返回。另一端的-1超時導致適配器上的讀取始終立即返回。 #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_open()。參數,snaplen,標志和to_ms值得一些解釋。
snaplen指定要捕獲的數據包的部分。在某些操作系統(如xBSD和Win32)上,數據包驅動程序可以配置為僅捕獲任何數據包的初始部分:這會減少要復制到應用程序的數據量,從而提高捕獲效率。在這種情況下,我們使用的值65536高于我們可能遇到的最大MTU值。以這種方式,我們確保應用程序將始終收到整個數據包。
標志:最重要的標志是指示適配器是否將處于混雜模式的標志。在正常操作中,適配器僅捕獲來自網絡的分發給它的分組; 因此,其他主機交換的數據包被忽略。相反,當適配器處于混雜模式時,它將捕獲所有數據包是否注定到它。這意味著在共享介質(如非交換式以太網)上,WinPcap將能夠捕獲其他主機的數據包。混雜模式是大多數捕獲應用程序的默認模式,因此我們在以下示例中啟用它。
to_ms指定讀取超時(以毫秒為單位)。即使沒有來自網絡的數據包,適配器上的讀取(例如,使用pcap_dispatch()或pcap_next_ex())將始終在to_ms毫秒之后返回。如果適配器處于統計模式,to_ms還會定義統計報告之間的間隔。將to_ms設置為0表示沒有超時,如果沒有數據包到達,則適配器上的讀取將永遠不會返回。另一端的-1超時導致適配器上的讀取始終立即返回。 #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()啟動。這兩個函數非常相似,不同之處在于pcap_ dispatch()返回(盡管不能保證)超時時pcap_loop()不會返回,直到cnt數據包被捕獲為止,因此它可以在利用不足的網絡。pcap_loop()足以用于此示例,而pcap_dispatch()通常用于更復雜的程序中。
這兩個函數都有一個回調參數packet_handler,指向一個將接收數據包的函數。該函數由libpcap為來自網絡的每個新數據包調用,并接收通用狀態(對應于pcap_loop()和pcap_dispatch()的用戶參數),該報頭具有數據包的一些信息,如時間戳和長度,數據包的實際數據包括所有協議頭。請注意,幀CRC通常不存在,因為在幀驗證后由網絡適配器刪除它。還要注意,大多數適配器丟棄CRC錯誤的數據包,因此WinPcap通常不能捕獲它們。
上述示例從pcap_pkthdr頭提取每個數據包的時間戳和長度,并將其打印在屏幕上。
請注意,使用pcap_loop()可能存在缺點,主要涉及到數據包捕獲驅動程序調用處理程序的事實;?因此用戶應用程序沒有直接的控制權。另一種方法(并且具有更多可讀程序)是使用pcap_next_ex()函數,該函數在下一個示例中顯示(捕獲不帶回調的數據包)。
新人創作打卡挑戰賽發博客就能抽獎!定制產品紅包拿不停!
總結
以上是生活随笔為你收集整理的c++ winpcap开发(3)的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: HDOJ 1285 确定比赛名次(拓扑排
- 下一篇: 2018年第九届蓝桥杯—C/C++程序设