我的场景,我正在收集网络数据包,如果数据包与网络过滤器匹配,我想记录连续数据包之间的时间差,最后一部分是不起作用的部分。我的问题是,无论我使用什么C计时器功能,我都无法获得准确的亚秒级测量。我试过了:gettimeofday(),clock_gettime()和clock()。
我正在寻找帮助,弄清楚为什么我的计时代码无法正常工作。
我在cygwin环境中运行。 编译选项:gcc -Wall capture.c -o capture -lwpcap -lrt
代码段:
/*globals*/
int first_time = 0;
struct timespec start, end;
double sec_diff = 0;
main() {
pcap_t *adhandle;
const struct pcap_pkthdr header;
const u_char *packet;
int sockfd = socket(PF_INET, SOCK_STREAM, 0);
.... (previous I create socket/connect - works fine)
save_attr = tty_set_raw();
while (1) {
packet = pcap_next(adhandle, &header); // Receive a packet? Process it
if (packet != NULL) {
got_packet(&header, packet, adhandle);
}
if (linux_kbhit()) { // User types message to channel
kb_char = linux_getch(); // Get user-supplied character
if (kb_char == 0x03) // Stop loop (exit channel) if user hits Ctrl+C
break;
}
}
tty_restore(save_attr);
close(sockfd);
pcap_close(adhandle);
printf("\nCapture complete.\n");
}
在got_packet中:
got_packet(const struct pcap_pkthdr *header, const u_char *packet, pcap_t * p){ ... {
....do some packet filtering to only handle my packets, set match = 1
if (match == 1) {
if (first_time == 0) {
clock_gettime( CLOCK_MONOTONIC, &start );
first_time++;
}
else {
clock_gettime( CLOCK_MONOTONIC, &end );
sec_diff = (end.tv_sec - start.tv_sec) + ((end.tv_nsec - start.tv_nsec)/1000000000.0); // Packet difference in seconds
printf("sec_diff: %ld,\tstart_nsec: %ld,\tend_nsec: %ld\n", (end.tv_sec - start.tv_sec), start.tv_nsec, end.tv_nsec);
printf("sec_diffcalc: %ld,\tstart_sec: %ld,\tend_sec: %ld\n", sec_diff, start.tv_sec, end.tv_sec);
start = end; // Set the current to the start for next match
}
}
}
我使用Wireshark记录所有数据包进行比较,所以我希望我的计时器的差异与Wireshark相同,但事实并非如此。我对tv_sec的输出是正确的,但tv_nsec甚至没有关闭。假设wireshark有0.5秒的差异,我的计时器会说有一个1.999989728秒的差异。
答案 0 :(得分:0)
我不认为时钟是你的问题,而是你等待新数据的方式。您应该使用轮询功能来查看何时从套接字或键盘获得新数据。这将允许您的程序在没有新数据处理时休眠。这可能会使操作系统在您的程序有更好的数据处理和安排时更好。这也允许您退出程序而无需等待下一个数据包进入。或者,您可以尝试以非常高或实时优先级运行程序。
如果过滤可能需要很长时间,您应该考虑在获取数据包后获取第一个实例的当前时间。如果您尝试在快速繁忙的网络上捕获数据,则可能还需要考虑此程序的多个线程。特别是如果你有多个处理器,但是因为你正在做一些可能阻塞的pritnf
。我注意到你有一个函数将tty设置为原始模式,我假设它是标准输出tty。如果你实际上使用的串行终端可以减慢很多东西,但标准的xterm也可能很慢。您可能需要考虑将stdout
设置为完全缓冲而不是行缓冲。这应该加快输出。 (man setvbuf
)
答案 1 :(得分:0)
基本上,您需要使用带有higher resolution
的计时器另外,我没有检查libpcap,但我很确定libpcap可以为您提供接收每个数据包的时间。在这种情况下,您最接近Wireshark显示的内容。