在 linux 下用 C++ ping 的最佳方法是什么?

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/313712/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-08-27 14:34:01  来源:igfitidea点击:

What is the best method to ping in c++ under linux?

c++linux

提问by nios

I have to call ping from c++ code.I'd like to easily read the output for further utilizations.

我必须从 C++ 代码调用 ping。我想轻松读取输出以供进一步利用。

I have come up with two solutions:

我想出了两个解决方案:

  • use a fork and a pipe, redirect ping output to the pipe and then parse it
  • find a library suited for the purpose to use a ping(ip_addresss) function directly
  • 使用叉子和管道,将 ping 输出重定向到管道,然后解析它
  • 找到适合直接使用 ping(ip_addresss) 函数的库

I'd like the latter but i didn't find anything that was clearly a standard solution.

我想要后者,但我没有找到任何明显是标准解决方案的东西。

How would you do it ?

你会怎么做?

采纳答案by e.James

I would go with your first option. Linux is built around the concept of having small, specialized apps which do one thing really well, communicating with pipes. Your app shouldn't include a library to implement ping, since there is already a built-in command to do it, and it works very well!

我会选择你的第一个选择。Linux 是围绕拥有小型、专门的应用程序的概念而构建的,这些应用程序可以很好地完成一件事,即通过管道进行通信。您的应用程序不应包含用于实现 ping 的库,因为已经有一个内置命令可以执行此操作,而且效果很好!

回答by Nicola Bonelli

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

从教育的角度来看,调用外部二进制文件是非常不可取的。特别是对于发送ICMP echo请求这样的简单任务,你应该学习一点socket。

回答by omeraygor

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

回答by schnaader

You could try to use this code.

您可以尝试使用此代码

回答by orip

Check out BusyBox's source for 'ping'- you can use the ping4and ping6functions. Just be mindful of the GPL.

查看 BusyBox 的'ping' 源代码- 您可以使用ping4ping6函数。请注意 GPL。

Spawning 'ping' should work too - check out popen(2)for a simpler API that also runs a shell. If it's a problem, pipe+ fork+ execshould work.

生成 'ping' 也应该工作 - 查看popen(2)一个更简单的 API,它也运行一个 shell。如果这是一个问题,pipe+ fork+exec应该工作。

回答by nios

I've managed to do like this:

我设法这样做:

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

我使用 popen,它基本上创建了一个管道、fork 和 exec 然后,如果我需要,我可以用 pclose 等待。