Capturing ping output in c

How can I immediately write the output of the ping command through the pipeline?

Here is my code:

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; } 

When the program is finished, it will display the output at the same time. But I would like to immediately read the result when the program is executed.

+7
source share
5 answers

<stdio.h> buffered by default, and stdout is buffered by line.

Replace printf("%s", s); printf("%s", s); on printf("%s\n", s); (the final new line will fflush(NULL); stdout buffer) or add a call to fflush(NULL); right after him.

Actually, your question is not related to ping , but the channel is buffered.

You can make lower levels pipe , fork , dup2 , read syscalls and explicitly control the buffer on the pipe. Then calling poll can be useful.

You can use the ICMP pinging library, such as liboping , or instead perform an HTTP request (either using the wget program, or preferably libcurl , perhaps a simple HTTP HEAD request is enough). For general advice, avoid using a process with popen or system (since the available commands may not match on the target computer).

Read a good Linux programming book, for example http://advancedlinuxprogramming.com/

+8
source

Here is a little code that uses liboping to ping www.xively.com every second and displays the delay. You can install liboping static / dynamic library files and header files in your ubuntu field as follows: sudo apt-get install liboping0 liboping-dev oping

Then compile the following program with the above library ( gcc -o test test.c -loping ). And run the executable as root (sudo).

test.c:

  /* * 1. install liboping, eg `sudo apt-get install liboping0 liboping-dev oping` * 2. Compile with -loping, eg `gcc -o test test.c -loping` * 3. Execute using sudo as super user, eg `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; } 

Output:

 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 

liboping is good if you want to check the Internet connection from your Linux device, if your ISP or target does not block ICMP packets. If they are blocked, you can use some HTTP library to try to extract the index.html page from www.google.com or any other website and see if it succeeded.

+6
source

You cannot read it right away, and it does not print at the end of execution.

Displayed at the moment when

  • the pipe buffer is filled or

  • the pipe closes

You need to change the properties of the pipe.

+1
source

Replace printf("%s", s); on printf("%s\n", s);

\n will clear your buffer, and you will get the result immediately after the printf command is executed, and you do not need to wait for the program to complete ...

+1
source

Just enter the output of a new line, then stdout flush by changing cmd with

 char *cmds = "ping -c 3 google.com | awk ' /icmp/ { printf(\"%s\\n\", $0); } '"; FILE *cmd = popen ( cmds, "r" ); 

It works, verified by me.

Other methods will not work because the problem is with flushing the pipes and not with the current stdout process.

0
source

All Articles