Windows和Linux 平台下都有一个使用非常频繁的工具: ping

此工具主要是检验网络中两节点间传递的数据包是否可达,计算耗时等,其原理是使用ICMP协议发送echo,并得到目的主机的回显。

以下是实现了最基本ping 功能的C程序,一共有三个文件:

icmphd.h  —— 定义报文结构

icmphd.c ——实现其声明的函数

main.c —— 主函数入口

编译环境:

操作系统: win7 sp1

CPU :x86_64

编译器:

1) MinGW-GCC version 4.8.1 (tdm64-2)

2) Microsoft Visual Studio Ultimate 2012 version 11.0.50727.1 RTMREL

注:若使用的是MinGW-GCC,则编译时连接库: -lwsock32,否则因为编译器对函数的默认调用规则不同,无法在Windows SDK中找到

导出的符号(符号不匹配)。运行与调试时使用管理员权限,否则发送时报错,WinSock Error Code = 10013

源代码:

icmphd.h

/*author : ezdate : 2014/10/20describe : -
*/#ifndef _ICMPHD_H_
#   define _ICMPHD_H_#include <stdint.h># define DEF_DATA_LEN    0x10
// random number
// #    define DEF_IDENTIFY     0x0003#pragma pack (1)struct iphd {uint8_t m_cVersionAndHeaderLen;uint8_t m_cTypeOfService;uint16_t m_sTotalLenOfPacket;uint16_t m_sPacketID;uint16_t m_sSliceinfo;uint8_t m_cTTL;uint8_t m_cTypeOfProtocol;uint16_t m_sCheckSum;uint32_t m_uiSourIp;uint32_t m_uiDestIp;
};struct icmphd {uint8_t type;uint8_t code;uint16_t chksum;uint16_t identifier;uint16_t seqnum;    // big-endian
};struct icmppk {struct icmphd hd;uint8_t data [DEF_DATA_LEN];
};#pragma pack ()#  define ICMPHD_SIZE     (sizeof (struct icmphd))
#   define ICMPPK_SIZE     (sizeof (struct icmppk))
#   define IPHD_SIZE        (sizeof (struct iphd))extern struct icmppk*
create_icmppk (uint8_t, uint8_t, uint16_t);#endif // ~ _ICMPHD_H_

icmphd.c

/*author : ezdate : 2014/10/20describe : -
*/
#include "icmphd.h"
#include <stdlib.h>
#include <string.h>
#include <stdio.h>static uint16_t
icmp_cal_cksum(uint8_t*, int);struct icmppk*
create_icmppk (uint8_t _type, uint8_t _code, uint16_t _seq) {struct icmppk* pk = (struct icmppk*) malloc (ICMPPK_SIZE);if (pk != NULL) {int i = 0;memset (pk, 0, ICMPPK_SIZE);pk -> hd.type = _type;pk -> hd.code = _code;pk -> hd.identifier = 1;// big-endian((uint8_t*) (&(pk -> hd.seqnum))) [0] = (uint8_t) ((_seq & 0xff00) >> 8);((uint8_t*) (&(pk -> hd.seqnum))) [1] = _seq & 0x00ff;for (; i < DEF_DATA_LEN; i ++)   // random datapk -> data [i] = i + '0';pk -> hd.chksum = icmp_cal_cksum ((uint8_t*) pk, ICMPPK_SIZE);}return pk;
}static uint16_t
icmp_cal_cksum(uint8_t* _data,int _data_len) {int sum = 0;  int odd = _data_len & 0x01;  uint16_t* value = (uint16_t*) _data;  while (_data_len & 0xfffe) {  sum += *(uint16_t*) _data;  _data += 2;_data_len -= 2;}if (odd) {uint16_t tmp = ((*_data) << 8) & 0xff00;  sum += tmp;  }  sum = (sum >> 16) + (sum & 0xffff);  sum += (sum >> 16);  return ~sum;
}

main.c

/* author : ez date : 2015/7/11describe : -
*/#undef UNICODE#include "icmphd.h"
#include <stdlib.h>
#include <string.h>
#include <stdio.h>
#include <winsock2.h>
#include <time.h>#if defined _WIN32 || defined _WIN64
#include <windows.h>
#endif #if !defined MAKEWORD
#   define MAKEWORD(low,high) ((WORD)(((BYTE)(low)) | ((WORD)((BYTE)(high))) << 8))
#endif#pragma comment (lib, "ws2_32.lib")#    define ADDR_OFFSET   1
#   define println(___STR)     printf ("%s\n", ___STR)uint16_t sequence = 0;
time_t start = 0, end = 0;
uint32_t ip_num = 0;
char* ip_char = NULL;
struct icmppk* send_data;
uint8_t* rcv_data;
SOCKET sockfd = INVALID_SOCKET;
struct sockaddr_in local;static struct icmppk*
request_echo_icmp (/*const char* */);static void
dispose_resources ();static void
parse_reply_echo_icmp (struct icmppk*, void*);int
ipstr_to_numeric (const char*, int *);static
void usage_disp () {printf ("Usage: ping <ip_address>\n");
}static struct icmppk*
request_echo_icmp (/*const char* _dst_addr */) {uint16_t ip_numeric = 0;struct icmppk* hd = NULL;// create icmp requesthd = create_icmppk (8, 0, ++ sequence);return hd;
}static void
rcv_parse_reply_echo_icmp () {int rcv_len = 0;int frm_len = ICMPPK_SIZE;while (1) {rcv_len = recvfrom (sockfd, (char*) rcv_data, 0x100, 0,(struct sockaddr*) &local, &frm_len);if (rcv_len > 0) {struct icmppk* ptr = (struct icmppk*) (((uint8_t*) rcv_data) + IPHD_SIZE);if (((struct iphd*) rcv_data) -> m_uiSourIp == ip_num &&((struct iphd*) rcv_data) -> m_cTypeOfProtocol == IPPROTO_ICMP) {end = time (NULL);printf ("Reply from %s: bytes = %d, time = %d nm, req = %d, TTL = %d\n", ip_char,DEF_DATA_LEN, difftime (end, start),ntohs (ptr -> hd.seqnum),((struct iphd*) rcv_data) -> m_cTTL);start = end = 0;
#ifdef  _MSC_VERSleep (1000);
#elif  __GNUC__sleep (1);
#endifbreak;} else continue;} else /*if (rcv_len == 0)*/continue;// else  // break;}
}static void
display_frame (struct icmppk* _pk, int _len) {int i = 0;for (; i < _len; i ++)printf ("0x%02x ", ((uint8_t*) _pk) [i]);
}int
ipstr_to_numeric (const char* _str, int * _addr) {const char* index;unsigned char* addr = (unsigned char*) _addr;int isnumeric = 1;int i = 3;*_addr = 0;index = _str;while  ((*index) && (isnumeric))  {if (isdigit  ((unsigned char) *index))addr [i] = addr [i] * 10 + (*index  - '0');  // big-endianelse if (*index == '.') {i --;if (i == -1) isnumeric = 0;} else isnumeric = 0;index ++;}if (isnumeric && i)  return -1;   // errorif (isnumeric)  return 0; // successful
}int
main (int argc, char *argv []) {  WSADATA wsaData;struct sockaddr_in hints;int remte_addr = 0;int timeout = 1000;int res;if (argc < 2) {usage_disp ();return 0;}// Initialize Winsockres = WSAStartup (MAKEWORD (2,2), &wsaData);  if (res != 0) {printf("WSAStartup fault, error: %d\n", res);return 1;}rcv_data = (uint8_t*) malloc (0x100);memset (&hints, 0, sizeof (struct sockaddr_in)); memset (&local, 0, sizeof (struct sockaddr_in));hints.sin_family = AF_INET;hints.sin_addr.s_addr = ip_num = inet_addr (ip_char = argv [ADDR_OFFSET]);local.sin_family = AF_INET;local.sin_addr.s_addr = inet_addr ("127.0.0.1");sockfd = socket (AF_INET, SOCK_RAW,IPPROTO_ICMP);if (sockfd == INVALID_SOCKET) {printf ("Socket fault, error: %ld\n", WSAGetLastError ());  WSACleanup ();dispose_resources ();return 1;}printf ("Ping host %s\n", ip_char);while (1) {send_data = request_echo_icmp ();start = time (NULL);// send data to serverres = sendto (sockfd, (const char*) send_data, ICMPPK_SIZE, 0,(struct sockaddr*) &hints, sizeof (hints));if (res == SOCKET_ERROR) {printf ("Send Error : %d\n", WSAGetLastError ());closesocket (sockfd);WSACleanup ();dispose_resources ();return 1;}// receive from remotercv_parse_reply_echo_icmp ();}// shutdown (sockfd, SD_BOTH);closesocket (sockfd);WSACleanup(); dispose_resources ();return 0;
}static void
dispose_resources () {rcv_data && ( free (rcv_data), (rcv_data = NULL));send_data && ( free (send_data), (send_data = NULL));
}

当然因为写的有点匆忙,很多地方还需要改进,本想做成跨平台的(Windows与Linux),也只写了一点点。还有输入的内容没有过滤等

很多问题,不过算是基本能用,下图是我截取的,在我的电脑上运行的结果。欢迎提出宝贵的意见。

ping工具的C语言简单实现 (ICMP echo)相关推荐

  1. 利用 Linux tap/tun 虚拟设备写一个 ICMP echo 程序

    利用 Linux tap/tun 虚拟设备写一个 ICMP echo 程序 前面两篇文章已经介绍过 tap/tun 的原理和配置工具.这篇文章通过一个编程示例来深入了解 tap/tun 的程序结构. ...

  2. 【绿冰壶的脚本小屋】第二期:基于icmp协议开发简易ping工具

    [绿冰壶的脚本小屋]第二期:基于ICMP协议开发简易ping工具 任务目标:编写程序使用 ICMP 协议探测主机是否存活 任务要求: 1.理解ICMP协议的原理 2.实现代码,尽可能多的实现探测主机是 ...

  3. 利用ping/ipconfig/nslookup/dig/whois简单工具测试DNS

    利用ping/ipconfig/nslookup/dig/whois简单工具测试DNS 2010-09-21 23:08:54 标签:dig mx ptr nslookup dns [推送到技术圈] ...

  4. python实现一个简单的ping工具

    继上一篇计算checksum校验和,本章通过socket套接字,struct字节打包成二进制,select返回套接字的文件描述符的结合,实现一个简单的ping工具. #!/usr/bin/python ...

  5. ping 工具开发日记(1)

    ping 工具开发日记(1) 2021.1.15 hyp 0.准备 开发语言:python 3.8 开发环境:windows 7 开发工具:pycharm 应用功能:1.能实现不同系统(windows ...

  6. 高级计算机网络实验——c++实现ping工具

    高级计算机网络实验--c++实现ping工具 1.Prepare 若要实现Ping工具,需要提前做好以下工作: 了解ICMP协议以及Ping包的协议结构 实现Socket通信,能够对包进行封装和解析 ...

  7. python实现ping工具

    ping工具的实现 应课程设计的需要,需要完成以下内容,实现ping工具的使用 任务要求: 使用该工具可以测试目标主机的状态 根据ICMP回显请求和回显应答报文,使用该工具测试目标主机的状态. 程序应 ...

  8. 关于一个用VB编写的PING工具的问题

    我在互联网上找到一个用VB编写的程序,是PING一个计算机的IP是否能通的工具,我改了改,使用ADO重数据库中循环读取IP地址,并将测试后的状态写入到数据库,作完后运行是可以测试,但是速度太慢了,每循 ...

  9. 批量ping工具fping

    批量ping工具fping ping是各个系统自带的基于ICMP协议的主机探测工具.但该工具一次只能检测一个主机,不满足渗透测试批量探测的需要.Kali Linux提供一款批量探测工具fping.用户 ...

最新文章

  1. C++类与const关键字
  2. linux超实用的管理命令
  3. 2018蓝桥杯省赛---java---C---9(小朋友崇拜圈)
  4. 谱聚类(spectral clustering)原理总结
  5. 问题 B: 调整表中元素顺序(线性表)
  6. 扑克牌大小的充电宝,你有吗?
  7. 微型计算机系统与接口流水灯,单片机的LED流水灯系统设计2.doc
  8. 快速备份和还原 MySQL 数据库的另一种方法
  9. Microsoft Office Word一打开文档就弹出样式小窗口
  10. 成都国税打造全能“电子税务局”
  11. 李涛专家主讲PS高手之路经典视频教程(1G打包下载)
  12. 找出数组中重复的值和所在位置
  13. 警惕面试过程中的 PUA
  14. FLINK任务重启 Streaming File Sink落地hdfs的中间状态In-progress格式文件处理方案
  15. Magento二次开发哪家好呢?
  16. CCF过程记录以及经验总结
  17. LeetCode 题解随笔:贪心算法
  18. qml加载高德在线地图
  19. CAD填充颜色透明颜色设置
  20. 数据结构——图的定义和实现

热门文章

  1. 程序猿生存指南-29 朝花夕拾
  2. 管理感言_留住人才很重要
  3. webpack源码分析之五:sourcemap
  4. Unity项目如何组织目录结构
  5. 新一代开源数据可视化开放平台,是如何做实时大屏/报表的?
  6. 易观落子长沙成立大数据研发中心 聚力中南IT产业
  7. 计算机软件保护的对象是,软件著作权的保护对象和内容是什么
  8. 《python源码剖析》第一部分 作者:陈儒 - python的内建对象 <一>
  9. 文件IO(系统IO)
  10. 微信小程序组件库解析:图片上传与排序组件yImgPro