2010-10-14 81 views
0

我的场景,我正在收集网络数据包,如果数据包匹配网络过滤器我想记录连续数据包之间的时间差异,这最后一部分是不起作用的部分。我的问题是,无论使用什么C计时器功能,我都无法获得准确的亚秒测量结果。我试过了:gettimeofday(),clock_gettime()和clock()。网络接收计时器到毫秒分辨率

我正在寻找帮助,找出为什么我的计时代码无法正常工作。

我在cygwin环境中运行。 编译选项:GCC -Wall -o的capture.c捕捉-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

基本上,你将要使用的定时器与higher resolution

而且,我没有libpcap的检查,但我敢肯定,libpcap的可以给你在接收到每个数据包的时间。在这种情况下,它最接近Wireshark显示的内容。

+0

原来,你是对的 - libpcap处理它。在我的got_packet函数中,当收到数据包时,我传递const struct pcap_pkthdr *头,其中包含sec和usec分辨率。我把它称为:header-> ts.tv_sec,header-> ts。tv_usec,它给了我最好的时机。 – Shawn 2010-10-14 21:12:00

0

我不认为这是时钟是你的问题,而是你等待新数据的方式。您应该使用轮询功能来查看何时从套接字或键盘获得新数据。这将使您的程序在没有新数据进行处理时进入休眠状态。这可能会使操作系统在您的程序有更好的处理和更快安排时间。这也允许您退出程序,而不必等待下一个数据包进入。或者,您可以尝试以非常高或实时的优先级运行程序。

如果过滤需要很长时间,您应该考虑在获得数据包后第一次获取当前时间。如果您尝试在快速繁忙的网络上捕获数据,您可能还需要考虑此程序的多个线程。特别是如果你有多个处理器,但是你正在做一些可能会阻塞的处理器。我注意到你有一个函数将tty设置为原始模式,我假设它是标准输出tty。如果你实际上使用的串行终端可能会让速度变慢,但对xterm的标准化速度也会变慢。您可能需要考虑将stdout设置为完全缓冲而不是行缓冲。这应该加快产量。 (man setvbuf

+0

纠正我,如果我错了,但我认为我的主要while语句正在做你所描述的轮询,我看到一个数据包是否到达,或者如果用户输入退出字符,然后采取行动。我怎么能用更少的资源使用来做到这一点? – Shawn 2010-10-14 20:34:30

+0

轮询功能,例如'poll','select和'epoll',让您的程序在等待新输入时进入睡眠状态。 Linux(linux_kbhit提供了你正在使用的操作系统)有时会通过降低其动态优先级和/或提高进行大量睡眠的进程的动态优先级来惩罚处理CPU的程序(发生在等待IO或调用'pause()'或'nanosleep()')。 – nategoose 2010-10-14 20:55:09