vc++6.0或者更高版本vs新建win32 console项目,选简单的Hello world项目,删除自动生成的代码,增加如下代码,链接(F7)(不要运行)后在该项目的Debug目录下使用命令行方式运行程序。

// iping.cpp : Defines the entry point for the console application.
//#include "stdafx.h"#pragma comment(lib,"ws2_32.lib")
//#pragma pack(4) //字节对齐
#include   "winsock2.h"
#include   "stdlib.h"
#include   "stdio.h"#define ICMP_ECHO 8 //ICMP回显请求
#define ICMP_ECHOREPLY 0 //ICMP回显应答
#define ICMP_MIN    8 //ICMP数据包最短为8个字节
#define DEF_PACKET_SIZE    32   //默认数据包长度
#define DEF_PACKET_NUMBER  4   //默认发送ICMP请求的次数
#define MAX_PACKET  1024        //数据包最大长度//定义IP头部
typedef struct iphdr
{
    unsigned int h_len:4; // 头部长
    unsigned int version:4; // 版本号
    unsigned char tos; // 服务类型
    unsigned short total_len; // 总长度
    unsigned short ident; // 标识
    unsigned short frag_and_flags; //标志
    unsigned char ttl; //生存时间
    unsigned char proto; // 上层协议
    unsigned short checksum; // 校验和
    unsigned int sourceIP; //源IP
    unsigned int destIP; //目的IP
}IpHeader; // 定义ICMP 头部
typedef struct icmphdr
{
    BYTE i_type; //类型
    BYTE i_code; //代码
    USHORT i_cksum; //校验和
    USHORT i_id; //标识
    USHORT i_seq; //序列号

    ULONG timestamp; //数据
}IcmpHeader; void fill_icmp_data(char *, int); //填充icmp数据包
USHORT checksum(USHORT *, int); //计算校验和
int decode_resp(char *,int ,struct sockaddr_in *); //收到数据后解码void Usage(char *progname)//提示用户该程序使用方法
{
    printf("Usage:\n");
    printf("%s target [number of packets] [data_size]\n",progname);
    printf("datasize can be up to 1Kb\n");
} void main(int argc, char **argv)
{
    WSADATA wsaData; //初始化windows socket需要的参数
    SOCKET sockRaw;  //原始套接字
    struct sockaddr_in dest,from; //源、目的IP地址
    struct hostent * hp; //指针指向包含主机名、地址列表等信息的结构体
    int iRecv,iSend, datasize,times;
    int fromlen = sizeof(from);    int timeout = 1000;  //超时时间1000ms=1s
    int statistic = 0;  // 用于统计
    char *dest_ip;
    char *icmp_data;
    char *recvbuf;
    unsigned int addr=0;
    USHORT  seq_no = 0;
    int     i;

    if (WSAStartup(MAKEWORD(2,1),&wsaData) != 0)
    {
        printf("WSAStartup failed: %d\n",GetLastError());
        return;
    }   //使用方法不对时显示提示信息
    if (argc <2 )
    {
        Usage(argv[0]);
        return;
    }   //创建原始套接字
//  sockRaw = WSASocket(AF_INET, SOCK_RAW, IPPROTO_ICMP, NULL, 0, WSA_FLAG_OVERLAPPED);
    //注:为了使用发送接收超时设置(即设置SO_RCVTIMEO, SO_SNDTIMEO),
    //    必须将标志位设为WSA_FLAG_OVERLAPPED !
    sockRaw = socket(AF_INET, SOCK_RAW, IPPROTO_ICMP);

    // 创建原始套接字不成功
    if (sockRaw == INVALID_SOCKET)
    {
        printf("WSASocket() failed: %d\n", WSAGetLastError());
        return;
    }   //设定发送超时时间
    iRecv = setsockopt(sockRaw, SOL_SOCKET, SO_RCVTIMEO, (char*)&timeout, sizeof(timeout));
    if(iRecv == SOCKET_ERROR)
    {
        printf("failed to set recv timeout: %d\n",WSAGetLastError());
        return;
    }   //设定接收数据超时时间
    timeout = 1000;
    iRecv = setsockopt(sockRaw, SOL_SOCKET, SO_SNDTIMEO, (char*)&timeout, sizeof(timeout));
    if(iRecv == SOCKET_ERROR) {
        printf("failed to set send timeout: %d\n",WSAGetLastError());
        return;
    }
    memset(&dest,0,sizeof(dest));   //解析用户输入的目标地址
    hp = gethostbyname(argv[1]);
    if (!hp)
    {
        addr = inet_addr(argv[1]);
    }   //非法输入
    if ((!hp) && (addr == INADDR_NONE))
    {
        printf("Unable to resolve %s\n",argv[1]);
        return;
    }   //记录目标主机信息的结构体
    //地址
    if (hp != NULL)
        memcpy(&(dest.sin_addr),hp->h_addr,hp->h_length);
    else
        dest.sin_addr.s_addr = addr;   //协议族
    if (hp)
        dest.sin_family = hp->h_addrtype;
    else
        dest.sin_family = AF_INET;     //目标IP
    dest_ip = inet_ntoa(dest.sin_addr);
            //除了目标地址,还给出了Ping的次数
    if(argc>2)
    {
        times=atoi(argv[2]);
        if(times == 0)
             times = DEF_PACKET_NUMBER;
    }
    else
        times = DEF_PACKET_NUMBER;

    //还给出了数据大小
    if (argc >3)
    {
        datasize = atoi(argv[3]);      //给的是0,则用默认数据包大小
        if (datasize == 0)
            datasize = DEF_PACKET_SIZE;        //用户给出的数据包大小太大
        if (datasize >1024)
        {
            printf("WARNING : data_size is too large !\n");
            datasize = DEF_PACKET_SIZE;
        }
    }
    else
        datasize = DEF_PACKET_SIZE; 

    datasize += sizeof(IcmpHeader);   icmp_data = (char *)malloc(MAX_PACKET);
    recvbuf = (char *)malloc(MAX_PACKET); 

    if (!icmp_data)
    {
        printf("HeapAlloc failed %d\n",GetLastError());
        return;
    } 

    memset(icmp_data, 0, MAX_PACKET);   //填充ICMP数据包,类型、代码、标识等
    fill_icmp_data(icmp_data,datasize);     //提示正在ping目标主机
    printf("\nPinging %s ....\n\n",dest_ip);  //Ping多次
    for(i=0; i<times; i++)
    {
        //准备ICMP包头部数据
        ((IcmpHeader *)icmp_data)->i_cksum = 0;
        //取得以毫秒为单位的计算机启动后经历的时间间隔
        ((IcmpHeader *)icmp_data)->timestamp = GetTickCount();
        ((IcmpHeader *)icmp_data)->i_seq = seq_no++; //序列号递增
        ((IcmpHeader *)icmp_data)->i_cksum = checksum((USHORT*)icmp_data,datasize);//计算校验和

        //发送ICMP数据包
        iSend = sendto(sockRaw,icmp_data,datasize,0,(struct sockaddr*)&dest,sizeof(dest)); 

        //发送失败
        if (iSend == SOCKET_ERROR)
        {
            if (WSAGetLastError() == WSAETIMEDOUT)
            {
                printf("Request timed out.\n");
                continue;
            }
            printf("sendto failed: %d\n",WSAGetLastError());
            break;
        }       if (iSend < datasize )
        {
            printf("Only sent  %d bytes\n",iSend);
        }       //接收应答数据
        iRecv = recvfrom(sockRaw, recvbuf, MAX_PACKET, 0, (struct sockaddr*)&from, &fromlen); 

        //接收失败
        if (iRecv == SOCKET_ERROR)
        {
            if (WSAGetLastError() == WSAETIMEDOUT)
            {
                printf("Request timed out.\n");
                continue;
            }
            printf("recvfrom failed: %d\n",WSAGetLastError());
            break;
        }       //成功解码
        if(!decode_resp(recvbuf,iRecv,&from))
            statistic++; //记录成功接收响应数据包的次数

        Sleep(1000);
    }   //统计运行Ping命令的统计结果
    printf("\nPing statistics for %s \n",dest_ip);
    printf("    Packets: Sent = %d,Received = %d, Lost = %d (%2.0f%% loss)\n",times,
            statistic,(times-statistic), (float)(times-statistic)/times*100);   free(recvbuf);
    free(icmp_data);    closesocket(sockRaw);
    WSACleanup();   return;
} //收到响应IP数据包后,对其进行解码
int decode_resp(char *buf, int bytes,struct sockaddr_in *from)
{
    IpHeader *iphdr;
    IcmpHeader *icmphdr;
    unsigned short iphdrlen; 

    iphdr = (IpHeader *)buf;
    iphdrlen = (iphdr->h_len) * 4 ; //头部占几个节字节 

    if (bytes < iphdrlen + ICMP_MIN)
    {
        printf("Too few bytes from %s\n",inet_ntoa(from->sin_addr));
    }   //找到ICMP数据包开始的地方
    icmphdr = (IcmpHeader*)(buf + iphdrlen);
    if (icmphdr->i_type != ICMP_ECHOREPLY)
    {
        printf("non-echo type %d recvd\n",icmphdr->i_type);
        return 1;
    }   //是不是发给本程序的数据包
    if (icmphdr->i_id != (USHORT)GetCurrentProcessId())
    {
        printf("someone else''s packet!\n");
        return 1;
    }   printf("%d bytes from %s:", bytes, inet_ntoa(from->sin_addr));
    printf(" icmp_seq = %d. ",icmphdr->i_seq);
    printf(" time: %d ms ", GetTickCount()-icmphdr->timestamp); //发送到接收过程的经历的时间
    printf("\n");
    return 0;
} //计算校验和
USHORT checksum(USHORT *buffer, int size)
{
    unsigned long cksum=0; 

    while(size >1) {
        cksum+=*buffer++;
        size -=sizeof(USHORT);
    }
    if(size) {
        cksum += *(UCHAR*)buffer;
    }
    cksum = (cksum >> 16) + (cksum & 0xffff);
    cksum += (cksum >>16);
    return (USHORT)(~cksum);
} //填充ICMP数据包
void fill_icmp_data(char * icmp_data, int datasize)
{
    IcmpHeader *icmp_hdr;
    char *datapart; 

    icmp_hdr = (IcmpHeader *)icmp_data;
    icmp_hdr->i_type = ICMP_ECHO;
    icmp_hdr->i_code = 0;
    icmp_hdr->i_id = (USHORT)GetCurrentProcessId();
    icmp_hdr->i_cksum = 0;
    icmp_hdr->i_seq = 0;
    datapart = icmp_data + sizeof(IcmpHeader);    //数据区随便填充
    memset(datapart,17, datasize - sizeof(IcmpHeader));
}

windows下ping程序使用C语言实现相关推荐

  1. Windows下Qt程序打包

    Windows下Qt程序打包 将windeployqt.exe 目录添加到系统环境变量 windeployqt.exe目录如下: 命令行打包 1.打开命令行 2.执行打包命令 windeployqt ...

  2. windows下应用程序加载DLL动态链接库路径

    windows下应用程序加载动态链接库路径依次分别是: 举例D盘soft文件夹下存在了一个test.exe的执行文件,即d:\soft\test.exe,依赖test.dll动态链接库. ■程序的执行 ...

  3. 006 - Windows 下 C++ 程序以管理员运行(UAC)

    Windows 下 C++ 程序以管理员运行(UAC) MSVC 编译器 qmake 在 pro 文件中添加一行指令即可, QMAKE_LFLAGS += /MANIFESTUAC:"lev ...

  4. 全网最全的Windows下Anaconda2 / Anaconda3里Python语言实现定时发送微信消息给好友或群里(图文详解)...

    不多说,直接上干货! 缘由: (1)最近看到情侣零点送祝福,感觉还是很浪漫的事情,相信有很多人熬夜为了给爱的人送上零点祝福,但是有时等着等着就睡着了或者时间并不是卡的那么准就有点强迫症了,这是也许程序 ...

  5. c语言编译及下载环境变量,windows 下使用g++ 编译器-Go语言中文社区

    转自https://blog.csdn.net/xiaoliuliu2050/article/details/53420792 名词解释:GNU("Gnu's Not Unix"的 ...

  6. Windows下使用Rtools编译R语言包

    使用devtools安装github中的R源代码时,经常会出各种错误,索性搜了一下怎么在Windows下直接打包,网上的资料也是参差不齐,以下是自己验证通过的. 一.下载Rtools 下载地址:htt ...

  7. Windows下Mex程序的调试

    写一下在Windows下调试Matlab与C/C++混合编程程序的方法. 1 编写Mex源文件  2 使用-g选项编译Mex源文件 3 将Matlab进程绑定到VS编译器中  4 在VS中打开Mex源 ...

  8. linux子系统安装gromacs,科学网—Windows下GROMACS程序的编译 - 李继存的博文

    2015-12-07 22:12:05 总的来说, Windows下的GROMACS程序用于模拟意义不大, 对于长时间的模拟, 我都是放在Linux服务器上进行的. 但将Windows下的GROMAC ...

  9. Windows下Python程序打包小结

    这还是之前的文章,最近发现了,还是存在网上好找些. 当然现在我的观念有点不一样了,纯Windows下桌面应用,还是Winform为首选,遇到复杂动画时用WPF控件.跨平台桌面应用,可以选择MONO,还 ...

最新文章

  1. 对抗 Google优势 微软考虑收购雅虎
  2. SpringBoot jar包不支持jsp
  3. class priority_queue 简单介绍
  4. 计算ndvi值需要的数据_ENVI中计算植被覆盖指数
  5. python并发编程之多进程、多线程、异步和协程
  6. Tomcat服务器安装配置与web服务器介绍
  7. 深度学习13-cnn介绍(卷积神经网络简介)
  8. Linux中如何针对用户及组设置磁盘配额
  9. 常见的Java编程思想有哪些
  10. android热敏打印机图片乱码,小票打印机常见故障及解决方法,小票打印机打印乱码怎么办...
  11. 网易云音乐的所有歌手列表
  12. archlinux for wps 字体缺失解决办法
  13. 春季养肝注意三个行为,做对了一年少生病
  14. H3C用户入网配置(radius、domain、802.1x)
  15. 【C语言】计算圆周长以及面积
  16. Element-UI中打开本地文件
  17. json批量转换成label图像
  18. 使用ffmpeg转换文件格式,及ffmpeg参数说明(转)
  19. 逆向学习litevm篇
  20. 免外围电路ESP32/ESP8266系列单片机串口一键下载方案

热门文章

  1. 矢量图eps在word中的使用的方法
  2. 石子合并/能量项链【区间dp】
  3. 发现一个可以免费看电影听音乐的网站
  4. PYthon调整音乐音量,生成空白音乐
  5. HP存储2000FC基础操作方法
  6. 河南省三门峡市谷歌高清卫星地图下载
  7. 里程碑2无信号,修改基带
  8. 神界计算机丢失msvcp120.dll,修复:Win10系统msvcp120.dll丢失了
  9. [转]SAP R/3开发类及表/结构资料
  10. 多普达Dopod德版D900刷机有惊无险经历之总结