在c中捕获ping的输出

CJD*_*CJD 7 c linux pipeline

如何通过管道立即捕获ping命令的输出?

这是我的代码:

int main ()
{
    FILE *cmd = popen ( "ping -c 3 google.com | grep icmp", "r" );//ping google
    char *s = malloc ( sizeof ( char ) * 200 );
    while ( 1 )
    {
            fgets ( s, sizeof ( char )*200, cmd );
            printf ( "%s", s);//show outcome
            if ( strstr ( s, "icmp_req=3" ) != 0 )
                    break;
    }
    pclose ( cmd );
    return 0;
}
Run Code Online (Sandbox Code Playgroud)

程序完成后,将同时显示输出.但我想在程序执行时立即读取输出.

Bas*_*tch 8

<stdio.h> 默认情况下是缓冲的,并且stdout是行缓冲的.

替换你printf("%s", s);printf("%s\n", s);(结束换行符将刷新stdout缓冲区)或fflush(NULL);在它之后添加一个调用.

实际上,你的问题与之无关ping,但管道是缓冲的.

你可能做的较低水平pipe,fork,dup2,read系统调用和显式管理管道上的缓冲.然后调用poll可能是有用的.

您可以考虑使用像liboping这样的ICMP pinging库,或者考虑改为执行HTTP请求(使用wget程序,或者最好使用libcurl ;也许一个简单的HTTP HEAD请求就足够了).作为一般建议,避免使用popen或分配进程system(因为目标计算机上可用的命令可能不同).

阅读一些很好的Linux编程书,比如http://advancedlinuxprogramming.com/


lit*_*ead 6

这是一个小代码,它使用liboping每秒 ping www.xively.com并显示延迟.您可以在ubuntu框上安装liboping静态/动态库文件和头文件,如下所示:sudo apt-get install liboping0 liboping-dev oping

然后使用上面的库(gcc -o test test.c -loping)编译以下程序.并以超级用户(sudo)身份运行可执行文件.

test.c的:

 /*
  * 1. install liboping, e.g. `sudo apt-get install liboping0 liboping-dev oping`
  * 2. Compile with -loping, e.g. `gcc -o test test.c -loping`
  * 3. Execute using sudo as super user, e.g. `sudo ./test`
  */

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

int main(int argc, char **argv) {
    pingobj_t *ping;
    pingobj_iter_t *iter;

    if ((ping = ping_construct()) == NULL) {
        fprintf(stderr, "ping_construct failed\n");
        return -1;
    }
    printf("ping_construct() success\n");

    if (ping_host_add(ping, "www.xively.com") < 0) {
        const char * errmsg = ping_get_error(ping);
        fprintf(stderr, "ping_host_add(www.xively.com) failed. %s\n", errmsg);
        return -1;
    }
    printf("ping_host_add() success\n");

    while (1) {
        if (ping_send(ping) < 0) {
            fprintf(stderr, "ping_send failed\n");
            return -1;
        }
        printf("ping_send() success\n");

        for (iter = ping_iterator_get(ping); iter != NULL; iter =
                ping_iterator_next(iter)) {
            char hostname[100];
            double latency;
            unsigned int len;

            printf("ping_iterator_get() success\n");
            len = 100;
            ping_iterator_get_info(iter, PING_INFO_HOSTNAME, hostname, &len);
            len = sizeof(double);
            ping_iterator_get_info(iter, PING_INFO_LATENCY, &latency, &len);

            printf("hostname = %s, latency = %f\n", hostname, latency);
        }
        sleep(1);
    }
    printf("exiting...\n");

    ping_destroy( ping );

    return 0;
}
Run Code Online (Sandbox Code Playgroud)

输出:

anurag@anurag-PC:~$ sudo ./test
ping_construct() success
ping_host_add() success
ping_send() success
ping_iterator_get() success
hostname = www.xively.com, latency = 233.666000
ping_send() success
ping_iterator_get() success
hostname = www.xively.com, latency = 234.360000
ping_send() success
ping_iterator_get() success
hostname = www.xively.com, latency = 234.076000
ping_send() success
ping_iterator_get() success
hostname = www.xively.com, latency = 231.761000
ping_send() success
ping_iterator_get() success
hostname = www.xively.com, latency = 235.085000
^C
Run Code Online (Sandbox Code Playgroud)

如果你想从你的linux设备检查互联网连接,如果你的ISP或目标没有阻止ICMP数据包,那么liboping是好的.如果这些被阻止,您可以使用某个HTTP库尝试从www.google.com或任何其他网站获取index.html页面并检查是否成功