首頁
編程語言
C語言|JAVA編程
Python編程
網頁編程
ASP編程|PHP編程
JSP編程
數據庫
MYSQL數據庫|SqlServer數據庫
Oracle數據庫|DB2數據庫
您现在的位置: 程式碼之家 >> 編程語言 >  >> C語言 >> C++ >> 關於C++

C語言實現 Ping 命令完整源碼解析

     編輯:關於C++

本文提供一個完整的 ICMP Ping 實現,包含校驗和計算、數據封裝、發送接收、統計顯示等核心功能,基於 Linux 系統調用開發。

核心數據結構與常量

#define PACKET_SIZE 4096
#define MAX_WAIT_TIME 5
#define MAX_NO_PACKETS 3

char sendpacket[PACKET_SIZE];
char recvpacket[PACKET_SIZE];
int sockfd, datalen = 56;
int nsend = 0, nreceived = 0;
struct sockaddr_in dest_addr;
pid_t pid;
struct sockaddr_in from;
struct timeval tvrecv;

校驗和算法

unsigned short cal_chksum(unsigned short* addr, int len) {
    int nleft = len;
    int sum = 0;
    unsigned short* w = addr;
    unsigned short 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;
}

ICMP 報文封裝

int pack(int pack_no) {
    struct icmp* icmpp = (struct icmp*)sendpacket;
    icmpp->icmp_type = ICMP_ECHO;
    icmpp->icmp_code = 0;
    icmpp->icmp_cksum = 0;
    icmpp->icmp_seq = pack_no;
    icmpp->icmp_id = pid;

    int packsize = 8 + datalen;
    struct timeval* tval = (struct timeval*)icmpp->icmp_data;
    gettimeofday(tval, NULL);  // 記錄發送時間

    icmpp->icmp_cksum = cal_chksum((unsigned short*)icmpp, packsize);
    return packsize;
}

發送與接收邏輯

void send_packet() {
    while (nsend < MAX_NO_PACKETS) {
        nsend++;
        int packetsize = pack(nsend);
        if (sendto(sockfd, sendpacket, packetsize, 0, 
                   (struct sockaddr*)&dest_addr, sizeof(dest_addr)) < 0) {
            perror("sendto error");
            continue;
        }
        sleep(1);
    }
}

void recv_packet() {
    int n, fromlen;
    // 接收循環解析 ICMP 回應...
}

統計輸出

void statistics(int signo) {
    printf("\n-----------------PING statistics----------------\n");
    printf("%d packet transmitted,%d received,%%%d lost\n",
           nsend, nreceived, (nsend-nreceived)/nsend*100);
    close(sockfd);
    exit(1);
}

完整代碼可直接編譯運行,實現標準 Ping 功能。

  1. 上一篇文章:
  2. 下一篇文章:
Copyright © 程式碼之家 All Rights Reserved