|
|
今天的试验程序与前天的功能是一样的,只是在捕获数据包的时候前天的程序用的是pcap_loop(),今天的代码用的是pcap_next_ex()。基于pcap_loop()抓包机制的回调很方便而且在某些情况下是一个不错的选择。但是,处理回调有些时候不适用——它使得程序更复杂,尤其是在应用程序与多线程或C++类有关的情况下。而pcap_next_ex()有的时候用起来更加方便。 试验代码3:
#include <pcap.h> #include <remote-ext.h>
int main() { pcap_if_t* alldevs; pcap_if_t* d; int inum; int i = 0; pcap_t* adhandle; int res; char errbuf[PCAP_ERRBUF_SIZE]; struct tm* ltime; char timestr[16]; struct pcap_pkthdr* header; u_char* pkt_data;
/* 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); } else { printf(" (No description available)\n"); } }
if (i == 0) { printf("\nNo interfaces found! Make sure Winpcap is installed.\n"); return -1; }
/* Select an adapter */ printf("Enter the interface number (1 - %d):", i); scanf("%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 adpater */ for (d = alldevs, i = 0; i < inum - 1; d = d->next, ++ i);
/* Open the device */ if ((adhandle = pcap_open(d->name, /* name of the device */ 65536, /* portion of the packet to capture */ /* 65536 guarantees that the whole packet will be captured on all the link layers */ PCAP_OPENFLAG_PROMISCUOUS, /* promiscuous mode */ 1000, /* read timeout */ NULL, /* authentication on the remote machine */ errbuf /* error buffer */ )) == NULL) { fprintf(stderr, "\nUnable to open the adapter. %s is not supported by Winpcap\n", d->name);
/* Free the devices 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);
/* Retrieve the packets */ while ((res = pcap_next_ex(adhandle, &header, &pkt_data)) >= 0) { if (res == 0) { /* Timeout elapsed */ continue; } /* convert the timestamp to readable format */ ltime = localtime(&header->ts.tv_sec); strftime(timestr, sizeof(timestr), "%H:%M:%S", ltime); printf("%s, %.6d len:%d\n", timestr, header->ts.tv_usec, header->len); }
if (res == -1) { printf("Error reading the packets: %s\n", pcap_geterr(adhandle)); return -1; } return 1; }
函数1:
pcap_next_ex(pcap_t* p,
struct pcap_pkthdr** pkt_header,
const u_char* pkt_data
)
从一个网络接口或离线捕获方式(例如读文件)读取一个数据包。该函数被用来重新获得下一个可用的数据包,没有使用libpcap提供的传统的回调方法。pcap_next_ex用指向头和下一个被捕获的数据包的指针为pkt_header和pkt_data参数赋值。
返回值有下列几种情况:
1,数据包被正确读取
0,pcap_open_live()设置的超时时间到。在这种情况下pkt_header和pkt_data不指向有效数据包
-1,发生错误
-2,离线捕获的时候读取到EOF
我们通常使用pcap_next_ex()而不是pcap_next(),因为pcap_next()有些缺点。首先,pcap_next()效率低,因为它隐藏了回调方法但是还是依赖于pcap_dispatch;第二,它不能检测EOF,所以当从一个文件获取数据包时它不是很有用。
函数2:
u_char* pcap_next(pcap_t* p,
|