C++之编码实现ping的功能

本文档详细介绍了如何使用C++编程语言实现ping命令的功能,包括主要的代码结构和关键实现点。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

## ping_dev.h

#ifndef PING_DEV_H
#define PING_DEV_H

#include "typedef.h"

INT32 get_device_status(PCHAR pDevIp);
INT32 ping_fun(PCHAR pDevIp);
int ping_dev_by_icmp(PCHAR pDevIp);
int ping_dev_by_icmp_result();
UINT16 ping_dev_by_icmp_cksum(UINT16 *addr, UINT32 len);
int ping_dev_by_icmp_size(UINT32 pack_no);
VOID ping_dev_by_icmp_send();
VOID ping_dev_by_icmp_recv();
int ping_dev_by_icmp_upack(PCHAR buf, UINT32 len);
VOID ping_dev_by_icmp_timeval(struct timeval *out,struct timeval *in);

#endif

## ping_dev.cpp

#include "ping_dev.h"
#include "log.h"
#include <stdio.h>
#include <sys/time.h>
#include <sys/socket.h>
#include <netinet/in.h>
#include <unistd.h>
#include <netdb.h>
#include <errno.h>
#include <stdlib.h>
#include <stdio.h>
#include <signal.h>
#include <pthread.h>
#include <arpa/inet.h>
#include <sys/ioctl.h>
#include <net/if.h>
#include <sys/stat.h>
#include <netinet/in.h>
#include <netinet/ip.h>
#include <netinet/ip_icmp.h>
#include <netdb.h>
#include <time.h>

//check static device status
#define PACET_SIZE 	4096
#define MAX_WAIT_TIME	3
#define MAX_NO_PACKETS	3

pid_t pid;
int sockfd = -1 ,datalen = 56;
int nsend = 0,nreceived = 0;
static INT32 gDevPingFlag = -1;		//-1:no device is pinging now, 0:some device is pinging now
char sendpacket[PACET_SIZE] = {'\0'};
char recvpacket[PACET_SIZE] = {'\0'};
struct sockaddr_in dest_addr;
struct sockaddr_in from;
struct timeval tvrecv;

/*******************************************************************************************************
Funtion: get_device_status
Description:get status of all device,through ping
Iput:pDevIp:device ip addr
Output:
Return:0:connected,-1:disconnected
*******************************************************************************************************/
INT32 get_device_status(PCHAR pDevIp)
{
    INT32 iRet = -1;

    if(gDevPingFlag == 0)
        return -1;

    if(pDevIp == NULL || strlen(pDevIp) <= 0)
    {
        LOG_MSG(LOG_ERR,"device ip is incorrect!\n");
        return -1;
    }
    gDevPingFlag = 0;

    iRet = ping_fun(pDevIp);
    gDevPingFlag = -1;

    return iRet;
}

/*******************************************************************************************************
Funtion: ping_fun
Description:ping device by ip
Iput:pDevIp:device ip addr
Output:
Return:0:connected,-1:disconnected
*******************************************************************************************************/
INT32 ping_fun(PCHAR pDevIp)
{
    INT32 iRet = -1;

    if(pDevIp == NULL || strlen(pDevIp) <= 0)
    {
        return -1;
    }
#if 0
    char strPing[COMMON_CHAR_LEN] = {'\0'};
    sprintf(strPing,"%s %s %s","ping",pDevIp,"-c 3 2>&1 >/dev/null");

    iRet = SYSTEM(strPing);
#endif
    iRet = ping_dev_by_icmp(pDevIp);
    if(0 != iRet)
    {
        //LOG_MSG(LOG_ERR,"ping device(%s) failed\n",pDevIp);
    }

    return iRet;
}

/*******************************************************************************************************
Funtion: ping_dev_by_icmp
Description:get status of static device,through ping
Iput:pDevIp:device ip addr
Output:
Return:0:connected,-1:disconnected
*******************************************************************************************************/
int ping_dev_by_icmp(PCHAR pDevIp)
{
    int iRet = -1;

    nsend = 0;
    nreceived = 0;
    memset(sendpacket,'\0',PACET_SIZE);
    memset(recvpacket,'\0',PACET_SIZE);

    struct hostent *host;
    struct protoent *protocol;
    unsigned long inaddr = 01;
    int waittime = MAX_WAIT_TIME;
    int size = 20*1024;
    if((protocol = getprotobyname("icmp")) == NULL)
    {
        perror("getprotobyname");
        return -1;
    }
    if((sockfd = socket(AF_INET,SOCK_RAW,IPPROTO_ICMP)) < 0)
    {
        perror("socket error");
        return -1;
    }
    //setuid(getuid());
    setsockopt(sockfd,SOL_SOCKET,SO_RCVBUF,&size,sizeof(size));
    bzero(&dest_addr,sizeof(dest_addr));
    bzero(&from,sizeof(from));
    dest_addr.sin_family = AF_INET;

    if((inaddr = inet_addr(pDevIp)) == INADDR_NONE)  //is host name
    {
        if((host = gethostbyname(pDevIp)) == NULL)
        {
            perror("gethostbyname error");
            return -1;
        }
        memcpy((char *)&dest_addr,(char *)&inaddr,host->h_length);

    }
    else  //is ip addr
    {
        dest_addr.sin_addr.s_addr = inet_addr(pDevIp);
    }

    pid = getpid();
    ping_dev_by_icmp_send();
    ping_dev_by_icmp_recv();
    iRet= ping_dev_by_icmp_result();
    return iRet;
}

/*******************************************************************************************************
Funtion: GET_STATIC_DEV_STATUS_SEND_PACKET
Description:send icmp packet
Iput:
Output:
Return:
*******************************************************************************************************/
VOID ping_dev_by_icmp_send()
{
    int packsize;
    while(nsend < MAX_NO_PACKETS)
    {
        nsend++;
        packsize = ping_dev_by_icmp_size(nsend);
        if(sendto(sockfd,sendpacket,packsize,0,(struct sockaddr *)&dest_addr,sizeof(dest_addr)) < 0)
        {
            perror("sendto error");
            continue;
        }
        usleep(5);
    }
}

/*******************************************************************************************************
Funtion: GET_STATIC_DEV_STATUS_RECV_PACKET
Description:receive icmp packet head
Iput:
Output:
Return:
*******************************************************************************************************/

VOID ping_dev_by_icmp_recv()
{
    int n;
    socklen_t fromlen;
    extern int errno;
    //signal(SIGALRM,GET_STATIC_DEV_STATUS_STATISTICS);
    fromlen = sizeof(from);

    int maxfds = 0;
    fd_set readfds;
    struct timeval timeout;
    timeout.tv_sec = 0;
    timeout.tv_usec = 5;

    while(nreceived < nsend)
    {
        FD_ZERO(&readfds);
        FD_SET(sockfd,&readfds);
        maxfds = sockfd + 1;
        n = select(maxfds,&readfds,NULL,NULL,&timeout);
        if(n <= 0)
        {
            close(sockfd);
            sockfd = -1;
            return ;
        }

        //alarm(MAX_WAIT_TIME);
        if((n = recvfrom(sockfd,recvpacket,sizeof(recvpacket),0,(struct sockaddr *)&from,&fromlen)) < 0)
        {
            return ;
        }
        gettimeofday(&tvrecv,NULL);
        if(ping_dev_by_icmp_upack(recvpacket,n) == -1)
            return;
        nreceived++;
    }
}

/*******************************************************************************************************
Funtion: GET_STATIC_DEV_STATUS_UNPACK
Description:remove icmp packet head
Iput:
Output:
Return:0:success,-1:error
*******************************************************************************************************/
int ping_dev_by_icmp_upack(PCHAR buf, UINT32 len)
{
    int i,iphdrlen;
    struct ip *ip;
    struct icmp *icmp;
    struct timeval *tvsend;
    double rtt;
    ip = (struct ip *)buf;
    iphdrlen = ip->ip_hl<<2;
    icmp = (struct icmp *)(buf + iphdrlen);
    len -= iphdrlen;
    if(len < 8)
    {
        return -1;
    }
    if((icmp->icmp_type == ICMP_ECHOREPLY) && (icmp->icmp_id == pid))
    {
        tvsend = (struct timeval *)icmp->icmp_data;
        ping_dev_by_icmp_timeval(&tvrecv,tvsend);
        rtt = tvrecv.tv_sec * 1000 + tvrecv.tv_usec/1000;
        return 0;
    }
    else
    {
        return -1;
    }
}

/*******************************************************************************************************
Funtion: ping_dev_by_icmp_timeval
Description:one tineval - one timeval
Iput:
Output:
Return:
*******************************************************************************************************/
VOID ping_dev_by_icmp_timeval(struct timeval *out,struct timeval *in)
{
    if((out->tv_usec -= in->tv_usec) < 0)
    {
        --out->tv_sec;
        out->tv_usec += 1000000;
    }
    out->tv_sec -= in->tv_sec;
}

/*******************************************************************************************************
Funtion: ping_dev_by_icmp_result
Description:
Iput:
Output:
Return:
*******************************************************************************************************/
int  ping_dev_by_icmp_result()
{
    int iRet = -1;
    if(nsend == nreceived)
    {
        iRet = 0;
    }
    else
    {
        iRet = -1;
    }
    close(sockfd);
    sockfd = -1;
    return iRet;

}
/*******************************************************************************************************
Funtion: GET_STATIC_DEV_STATUS_CAL_CHKSUM
Description:check
Iput:
Output:
Return:
*******************************************************************************************************/
UINT16 ping_dev_by_icmp_cksum(UINT16 *addr, UINT32 len)
{
    UINT32 nleft = len;
    UINT32 sum = 0;
    UINT16 *w = addr;
    UINT32 answer = 0;

    while(nleft > 1)
    {
        sum += *w++;
        nleft -= 2;
    }
    if(nleft == 1)
    {
        *(unsigned char *)(&answer) = *(unsigned char *)w;
        sum += answer;
    }
    sum = (sum>>16)+ (sum&0xffff);
    sum += (sum>>16);
    answer =~ sum;
    return answer;
}
/*******************************************************************************************************
Funtion: GET_STATIC_DEV_STATUS_PACK
Description:set icmp packet
Iput:pack_no:
Output:
Return:
*******************************************************************************************************/
int ping_dev_by_icmp_size(UINT32 pack_no)
{
    int i,packsize;
    struct icmp *icmp;
    struct timeval *tval;
    icmp = (struct icmp*)sendpacket;
    icmp->icmp_type = ICMP_ECHO;
    icmp->icmp_code = 0;
    icmp->icmp_cksum = 0;
    icmp->icmp_seq = pack_no;
    icmp->icmp_id = pid;
    packsize = 8 + datalen;
    tval = (struct timeval *)icmp->icmp_data;
    gettimeofday(tval,NULL);
    icmp->icmp_cksum = ping_dev_by_icmp_cksum((UINT16 *)icmp,packsize);

    return packsize;
}


评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值