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

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

代码示例:

#include  #include  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 

但是如果我通过’lsof’在C程序中更改’tshark’命令参数,我就可以得到标准输出。

 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处理打印的数据包计数和信息的方式不同。

问候,汤姆

好吧,即使我最终不使用这种与tshark一起工作的方式,我想我找到了使用的选项以便使用tshark。 从手册页中, 选项-l

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

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

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