用C中的popen捕获tshark标准输出

时间:2014-10-03 10:29:52

标签: c pipe stdout popen tshark

我试图通过C中的程序捕获 tshark 的标准输出。 为此,我使用 popen()调用来打开tshark进程并从返回的FILE流中读取。

代码示例:

#include <stdio.h>
#include <stdlib.h>

int main() {

    FILE* pipe_fd = popen("tshark -i eth0 -R icmp -2 -T fields -e icmp.checksum -e icmp.seq", "r");
    //FILE* pipe_fd = popen("lsof", "r");

    if (!pipe_fd) {
        fprintf(stderr, "popen failed.\n");
        return EXIT_FAILURE;
    }

    char buffer[2048];
    while (NULL != fgets(buffer, sizeof(buffer), pipe_fd)) {
        fprintf(stdout, "SO: %s", buffer);
    }

    pclose(pipe_fd);
    printf("tdr FINISHED!\n");
    return 0;
}

当我运行它时,我只得到数据包编号,即,我没有数据包字段信息,只有数据包的数量,每个数字在同一个地方覆盖前一个(没有行滚动发生)。

像这样的东西,我想4包:

tomas@ubuntu64:~$ sudo ./main
tshark: Lua: Error during loading:
 [string "/usr/share/wireshark/init.lua"]:46: dofile has been disabled due to running Wireshark as superuser. See http://wiki.wireshark.org/CaptureSetup/CapturePrivileges for help in running Wireshark as an unprivileged user.
Running as user "root" and group "root". This could be dangerous.
Capturing on 'eth0'
4 

但如果我改变了C程序,那么&#39; tshark&#39;通过&#39; lsof&#39;命令参数,我得到标准输出就好了。

tomas@ubuntu64:~$ sudo ./main
lsof: WARNING: can't stat() fuse.gvfsd-fuse file system /run/user/1000/gvfs
      Output information may be incomplete.
SO: COMMAND     PID   TID       USER   FD      TYPE             DEVICE SIZE/OFF       NODE NAME
SO: init          1             root  cwd       DIR                8,1     4096          2 /
SO: init          1             root  rtd       DIR                8,1     4096          2 /
SO: init          1             root  txt       REG                8,1   265848     791529 /sbin/init
SO: init          1             root  mem       REG                8,1    47712     824514 /lib/x86_64-linux-gnu/libnss_files-2.19.so
...

通过这个结果,我假设 tshark 将信息发送到标准输出的方式有一些特殊之处。有谁知道这种行为? 我要查看tshark源代码,看看它是否可以澄清它。

最后一点。

当我在shell中运行tshark时,我经常会丢失数据包,例如:

tomas@ubuntu64:~$ sudo tshark -i eth0 -R icmp -2 -T fields -e icmp.checksum -e icmp.seq
tshark: Lua: Error during loading:
 [string "/usr/share/wireshark/init.lua"]:46: dofile has been disabled due to running Wireshark as superuser. See http://wiki.wireshark.org/CaptureSetup/CapturePrivileges for help in running Wireshark as an unprivileged user.
Running as user "root" and group "root". This could be dangerous.
Capturing on 'eth0'
0x0ee5  63045
1 0x8ae3    63046
2 0xcfdf    63047
3 0xe4d9    63048
4 0x9db7    63049
5 0x6798    63050
6 0x0175    63051
7 0x9e54    63052
0xa654  63052
9 0xe050    63053
0xe850  63053
11 0x8389   63054
0x8b89  63054
13 0x9b81   63055
0xa381  63055

缺少打印的数据包编号8,10,12,14。

当我将stdout重定向到文件时,它不会发送计数:

tomas@ubuntu64:~$ sudo tshark -i eth0 -R icmp -2 -T fields -e icmp.checksum -e icmp.seq > kk
tomas@ubuntu64:~$ cat kk 
0x2073  63321
0x2873  63321
0x7c6a  63322

tshark处理打印数据包计数和信息的另一个线索。

此致 汤姆

1 个答案:

答案 0 :(得分:0)

好吧,即使我最终没有使用这种使用tshark的方式,我想我找到了使用这个选项来 popen tshark。在手册页中,选项-l

  

打印每个数据包的信息后,刷新标准输出。 (严格来说,如果-V是,那么这不是行缓冲的   规定;但是,如果-V不是,它与行缓冲相同   指定,因为每个数据包只打印一行,并且,如-l所示   通常在将实时捕获传递给程序或脚本时使用,所以   一旦看到数据包,数据包的输出就会显示出来   解剖,它应该像真正的线缓冲一样工作。我们的确是   这是Microsoft Visual C ++ C中缺陷的解决方法   库)。

     

将TShark的输出传递给另一个时,这可能很有用   程序,因为它意味着输出管道的程序   一旦TShark看到,就会看到数据包的解剖数据   数据包并生成该输出,而不是只在它时才看到它   包含该数据的标准输出缓冲区填满。

我测试了它,它似乎工作。 以防任何人需要它。