What is the best method for ping in C ++ under linux?

I need to call ping from C ++ code. I would like to read the result easily for future reference.

I came up with two solutions:

  • use a plug and a tube, redirect the ping output to the tube and then analyze it
  • find a library suitable for using the ping function (ip_addresss) directly

I would like the latter, but I did not find anything that would be a standard solution.

How do you do this?

+6
c ++ linux
source share
6 answers

I would go with your first option. Linux is based on the concept of small specialized applications that do an excellent job of exchanging data with pipes. Your application should not include a library for implementing ping, since there is already a built-in command for this, and it works very well!

+3
source share

From an educational point of view, the use of external binary code is very impractical . Especially for a simple task, such as sending an ICMP echo request, you should learn a bit of socket.

+7
source share
#include <fcntl.h> #include <errno.h> #include <sys/socket.h> #include <resolv.h> #include <netdb.h> #include <netinet/in.h> #include <netinet/ip_icmp.h> #define PACKETSIZE 64 struct packet { struct icmphdr hdr; char msg[PACKETSIZE-sizeof(struct icmphdr)]; }; int pid=-1; struct protoent *proto=NULL; int cnt=1; /*--------------------------------------------------------------------*/ /*--- checksum - standard 1s complement checksum ---*/ /*--------------------------------------------------------------------*/ unsigned short checksum(void *b, int len) { unsigned short *buf = b; unsigned int sum=0; unsigned short result; for ( sum = 0; len > 1; len -= 2 ) sum += *buf++; if ( len == 1 ) sum += *(unsigned char*)buf; sum = (sum >> 16) + (sum & 0xFFFF); sum += (sum >> 16); result = ~sum; return result; } /*--------------------------------------------------------------------*/ /*--- ping - Create message and send it. ---*/ /* return 0 is ping Ok, return 1 is ping not OK. ---*/ /*--------------------------------------------------------------------*/ int ping(char *adress) { const int val=255; int i, sd; struct packet pckt; struct sockaddr_in r_addr; int loop; struct hostent *hname; struct sockaddr_in addr_ping,*addr; pid = getpid(); proto = getprotobyname("ICMP"); hname = gethostbyname(adress); bzero(&addr_ping, sizeof(addr_ping)); addr_ping.sin_family = hname->h_addrtype; addr_ping.sin_port = 0; addr_ping.sin_addr.s_addr = *(long*)hname->h_addr; addr = &addr_ping; sd = socket(PF_INET, SOCK_RAW, proto->p_proto); if ( sd < 0 ) { perror("socket"); return 1; } if ( setsockopt(sd, SOL_IP, IP_TTL, &val, sizeof(val)) != 0) { perror("Set TTL option"); return 1; } if ( fcntl(sd, F_SETFL, O_NONBLOCK) != 0 ) { perror("Request nonblocking I/O"); return 1; } for (loop=0;loop < 10; loop++) { int len=sizeof(r_addr); if ( recvfrom(sd, &pckt, sizeof(pckt), 0, (struct sockaddr*)&r_addr, &len) > 0 ) { return 0; } bzero(&pckt, sizeof(pckt)); pckt.hdr.type = ICMP_ECHO; pckt.hdr.un.echo.id = pid; for ( i = 0; i < sizeof(pckt.msg)-1; i++ ) pckt.msg[i] = i+'0'; pckt.msg[i] = 0; pckt.hdr.un.echo.sequence = cnt++; pckt.hdr.checksum = checksum(&pckt, sizeof(pckt)); if ( sendto(sd, &pckt, sizeof(pckt), 0, (struct sockaddr*)addr, sizeof(*addr)) <= 0 ) perror("sendto"); usleep(300000); } return 1; } /*--------------------------------------------------------------------*/ /*--- main - look up host and start ping processes. ---*/ /*--------------------------------------------------------------------*/ int main(int argc, char *argv[]) { if (ping("www.google.com")) printf("Ping is not OK. \n"); else printf("Ping is OK. \n"); return 0; } 
+6
source share

You can try to use this code .

+2
source share

Drop the BusyBox source for ping - you can use the ping4 and ping6 . Just remember the GPL.

A "ping" malfunction should work too - check popen(2) for a simpler API that also launches the shell. If this is a problem, pipe + fork + exec should work.

+2
source share

I managed to do like this:

I use popen, which basically creates a pipe, fork and exec Then, if I need to, I can wait with pclose.

0
source share

All Articles