记不起在哪个项目中需要做一个检查设备在线状态的功能,可当时又没有设备的SDK可使用,网上找索很久,找到这款PING的小工具,简单适用,自己修改了一下,用起来超方便。 自己先攒起来再说。

[头文件]

#ifndef _PINGTOOL_H
#define _PINGTOOL_H#include <winsock2.h>
#include <iostream>
#pragma comment( lib, "ws2_32.lib" ) class CPintTool
{#define ICMP_ECHO 8             //回应请求类型的ICMP消息类型#define ICMP_ECHOREPLY 0        //回应答复型的ICMP消息类型#define ICMP_MIN 8              // ICMP数据报最小长度#define DEF_PACKET_SIZE 32     //默认数据报大小#define DEF_PACKET_NUMBER 3    //发送数据报的个数 #define MAX_PACKET 1024        //最大ICMP数据报大小public:CPintTool();~CPintTool();public:bool pintTo( char* destIP );private:SOCKET  sockRaw;int destlen, fromlen, bwrote, bread;sockaddr_in dest,from;char *icmp_data, *recvbuf;struct hostent *hp;unsigned short seq;//成员变量的定义char *Ipdest;                  //目标主机的IP地址int datasize;                  //ICMP消息的长度//接收到的ICMP消息数,每收到一条ICMP消息就加1
//    static  int    icmpcount=0; int    icmpcount; //IP头(20字节)struct IPHEAD { unsigned int   headlength:4;           // 4位头长度unsigned int   version:4;              // 4位版本unsigned char  tos;                    // 8位服务类型unsigned short totallength;            // 16位总长 unsigned short ip_id;                  // 16位标识unsigned short frag_and_flags;         //3个一位标识加分段偏移unsigned char  ttl;                    //8位存活时间unsigned char  protocal;               //8位协议类型 unsigned short ip_checksum;            //16位头校验和unsigned int   sourceIP;               //32位源IP地址unsigned int   destIP;                 //32位目标IP地址}; // ICMP 头(12字节)struct ICMPHEAD { unsigned char  type;               //类型(0,8)unsigned char  code;               //代码(0)unsigned short icmp_checksum;      //校验和unsigned short icmp_id;            //标识符unsigned short seq;                //序号unsigned long  timestamp;          //时间戳}; private://成员函数的定义//Fill_icmp_data函数:用于设置ICMP头部,填充ICMP消息void Fill_icmp_data(char * icmp_data, int datasize);//DecodeICMPHEAD函数:接受数据时从IP头中获取ICMP消息void DecodeICMPHEAD(char *recvbuf, int bread, sockaddr_in *from);//Checksum函数:用于求ICMP首部校验和unsigned short Checksum(unsigned short *buffer, int size);//Usage函数:表示程序的功能void Usage(char *progname);
};#endif //_PINGTOOL_H

[CPP文件]

#include <stdafx.h>
#include <iostream>
#include "PingTool.h"using namespace std;CPintTool::CPintTool()
:icmp_data( NULL )
,recvbuf( NULL )
,hp( NULL )
,seq( 0 )
,sockRaw( INVALID_SOCKET )
,datasize( DEF_PACKET_SIZE )     //数据包大小为DEF_PACKET_SIZE=32
{WSADATA  wsaData;//启动winsock失败,输出错误提示信息if (WSAStartup(MAKEWORD(2,2),&wsaData) != 0){ cout<<"WSAStartup  failed:"<<GetLastError();cout<<endl;return;}destlen = sizeof(sockaddr_in);fromlen = sizeof(sockaddr_in);
}CPintTool::~CPintTool()
{WSACleanup();
}bool CPintTool::pintTo( char* destIP )
{Ipdest= destIP; //默认目的地址为:202.119.81.120//创建套接字失败,输出错误信息提示sockRaw = WSASocket(AF_INET,SOCK_RAW,IPPROTO_ICMP,NULL, 0,WSA_FLAG_OVERLAPPED);if (sockRaw == INVALID_SOCKET) { cout<<"WSASocket() failed:"<<GetLastError();cout<<endl;return false;}//设定发送数据时最长等待时间timeout=1000msint timeout=1000;bread=setsockopt(sockRaw,SOL_SOCKET,SO_RCVTIMEO,(char *)&timeout,sizeof(timeout));if(bread==SOCKET_ERROR){cout<<"setsockopt(SO_RCVTIMEO)  failed:"<<WSAGetLastError();cout<<endl;return false;}//设定接收数据时最长等待时间timeout=1000mstimeout=1000;bread=setsockopt(sockRaw,SOL_SOCKET,SO_SNDTIMEO,(char *)&timeout,sizeof(timeout));if(bread==SOCKET_ERROR){cout<<"setsockopt(SO_SNDTIMEO) failed:"<<WSAGetLastError();cout<<endl;return false;}//解析目的地址的名称dest.sin_family=AF_INET;if(dest.sin_addr.s_addr=inet_addr(Ipdest)){    //inet_addr将IP地址转换成网络地址if((hp=gethostbyname(Ipdest))!=NULL){//gethostbyname主机信息memcpy(&(dest.sin_addr),hp->h_addr,hp->h_length); //复制内存dest.sin_family=hp->h_addrtype;cout<<"dest.sin_addr="<<inet_ntoa(dest.sin_addr);cout<<endl<<'\n';}else{cout<<"gethostbyname() failed:"<<WSAGetLastError();cout<<endl;return false;}}//建立一个ICMP数据包datasize+=sizeof(ICMPHEAD);//为要发送的数据申请内存空间,最大值为1024icmp_data=new char[MAX_PACKET];//为要接收的数据申请内存空间,最大值为1024recvbuf=new char[MAX_PACKET];//分配内存失败,输出提示信息if(!icmp_data){cout<<"new char[] failed:"<<WSAGetLastError();cout<<endl;return false;}          //将ICMP信息所在空间清零memset(icmp_data,0,MAX_PACKET);//设置ICMP信息头部Fill_icmp_data(icmp_data,datasize);//发送和接收数据,循环三次icmpcount = 0;for(int i=0;i<3;i++){//ICMP信息封装((ICMPHEAD*)icmp_data)->icmp_checksum=0;((ICMPHEAD*)icmp_data)->timestamp = GetTickCount(); ((ICMPHEAD*)icmp_data)->seq=seq++;((ICMPHEAD*)icmp_data)->icmp_checksum = Checksum((unsigned short*)icmp_data,datasize);//发送数据bwrote = sendto(sockRaw,icmp_data,datasize,0,(sockaddr*)&dest,destlen);if (bwrote == SOCKET_ERROR){if (WSAGetLastError() == WSAETIMEDOUT){cout<<"Request timed out."<<endl;continue;}else {cout<<"sendto( ) failed:"<<WSAGetLastError();cout<<endl;return false;}}//显示实际发送的字节数cout<<"Pinging "<<inet_ntoa(dest.sin_addr)<<" with ";cout<<bwrote<<" bytes of data:";cout<<endl;//接收数据bread=recvfrom(sockRaw,recvbuf,MAX_PACKET,0,(sockaddr*)&from,&fromlen);if (bread == SOCKET_ERROR){if (WSAGetLastError() == WSAETIMEDOUT){cout<<"Request timed out."<<endl;continue;}cout<<"recvfrom() failed: "<<WSAGetLastError();cout<<endl;return false;}//打开接收到的数据,从中提取ICMP头信息DecodeICMPHEAD(recvbuf,bread,&from);//等待1s钟Sleep(1000);}//输出发送的数据包数、接收的数据包数和丢失的数据包数cout<<endl;cout<<"Ping statistics for "<<inet_ntoa(dest.sin_addr)<<":"<<endl;cout<<"    Packets:sent=4,";cout<<"Received="<<icmpcount;cout<<",Lost="<<DEF_PACKET_NUMBER-icmpcount;cout<<"("<<((float)(DEF_PACKET_NUMBER-icmpcount)/DEF_PACKET_NUMBER)*100;cout<<"%loss)";cout<<endl;//释放资源,关闭winsockif(sockRaw!=INVALID_SOCKET)closesocket(sockRaw);delete[] recvbuf;delete[] icmp_data;if ( icmpcount == 0 )return false;return true;
}//Fill_icmp_data函数:用于设置ICMP头部,填充ICMP消息
void CPintTool::Fill_icmp_data(char * icmp_data, int datasize)
{ICMPHEAD *icmphead=NULL; char *datapart=NULL; icmphead = (ICMPHEAD*)icmp_data; icmphead->type = ICMP_ECHO;        //ICMP_ECHO=8icmphead->code = 0;                //类型为8,代码为0,表示回应请求icmphead->icmp_checksum = 0;icmphead->icmp_id = (unsigned short)GetCurrentProcessId();  datapart = icmp_data + sizeof(ICMPHEAD);//具体内容的首地址指针//初始化数据包内容部分for( int i=0;i < (datasize-sizeof(ICMPHEAD)); i++,datapart++ )*datapart=0;
}
//DecodeICMPHEAD函数:接受数据时从IP头中获取ICMP消息
void CPintTool::DecodeICMPHEAD(char *recvbuf, int bread, sockaddr_in *from)
{ IPHEAD           *iphead=NULL; ICMPHEAD         *icmphead=NULL; DWORD            tick;unsigned short   iphdrlen;iphead = (IPHEAD *)recvbuf; //32位字的个数乘以4即字节个数iphdrlen = (iphead->headlength) * 4 ;//获取操作系统启动至今所经过的时间(ms)tick=GetTickCount();if (bread < (iphdrlen + ICMP_MIN)) { cout<<"Too few bytes from: "<<inet_ntoa(from->sin_addr);cout<<endl;} icmphead = (ICMPHEAD*)(recvbuf + iphdrlen); //ICMP消息始于IP头之后//若ICMP消息类型并非查询,则输出相应信息类型if (icmphead->type != ICMP_ECHOREPLY) { cout<<"nonecho type "<<int(icmphead->type)<<" received";cout<<endl;} //确认收到的应答ICMP消息是否是对发送出去的消息的回应//若其表示与当前进程不符,则输出出错信息if (icmphead->icmp_id != (unsigned short)GetCurrentProcessId()) { cout<<"It's someone else's packet!"<<endl;return;}//输出收到信息的内容:主机地址,icmp消息序号,回应时间,存活时间cout<<"Reply from "<<inet_ntoa(from->sin_addr);cout<<" bytes="<<bread-iphdrlen;cout<<" time: "<<GetTickCount()-icmphead->timestamp<<" ms ";cout<<" seq="<<icmphead->seq;cout<<endl;icmpcount++;
} //Checksum函数:用于求ICMP首部校验和
unsigned short CPintTool::Checksum(unsigned short *buffer, int size)
{ unsigned long cksum=0;            //设校验和初值为0 while(size >1)  { cksum+=*buffer++;             //求各个16位数字之和size -=sizeof(unsigned short); } if(size) { cksum += *(unsigned char*)buffer;              } cksum = (cksum >> 16) + (cksum & 0xffff);  //高位与低位相加cksum += (cksum >>16);                     //加上进位return (unsigned short)(~cksum);                   //取反得到校验和
} //Usage函数:表示程序的功能
void CPintTool::Usage(char *progname)
{cout<<"Usage:"<<progname<<" <host>"<<endl;cout<<"       host          remote machine to Ping"<<endl;cout<<endl;
}

[用法:]

#include "stdafx.h"
#include <iostream>
#include "PingTool.h"int _tmain(int argc, _TCHAR* argv[])
{CPintTool pingT;char* ipdest = "192.168.3.254";bool boo = pingT.pintTo( ipdest );if ( boo )
    {
<span style="white-space:pre">  </span>std::cout << " 目标地址可达! " << std::endl;
     }
     else
     {
<span style="white-space:pre">  </span>std::cout << " 目标地址不可达!!! " << std::endl;
      }return 0;}

收藏一个Ping的小工具类,可用于网络中检测目的设备是否在线相关推荐

  1. aspose 转pdf表格大小乱了_自己写了一个小工具类:pdf转word,没有页数和大小限制,保真!...

    昨天下午遇到一个问题,想把一个比较大的pdf转化为word,结果使用了各种工具都收费.想着干脆写一个小工具吧,一开始使用的python等等试了好几个网上的代码,结果全都失真.于是乎不得不花了一下午自己 ...

  2. 一个Android下ping的简单工具类

    这是一个自己写的Android下的ping的简单工具类,主要是通过ping获取到返回字符串之后截取信息得到自己想要的数据.不多说,上源码 import java.io.BufferedReader; ...

  3. python打字_使用Python制作一个打字训练小工具

    一.写在前面 说道程序员,你会想到什么呢?有人认为程序员象征着高薪,有人认为程序员都是死肥宅,还有人想到的则是996和 ICU. 别人眼中的程序员:飞快的敲击键盘.酷炫的切换屏幕.各种看不懂的字符代码 ...

  4. 封装一个常用的js工具类

    /*** @author:水痕* @timer:2016-07-28* @email:332904234@qq.com* @version:1.0* @title:封装一个自己常用的工具类js* @n ...

  5. java web 项目 常用 小工具类 ~~~~

    java web 项目 常用 小工具类 ~~~~ 一 .DateUtil  日期工具类 package com.devframe.common.util;import java.text.Simple ...

  6. python 编写实用小工具-使用Python制作一个打字训练小工具

    一.写在前面 说道程序员,你会想到什么呢?有人认为程序员象征着高薪,有人认为程序员都是死肥宅,还有人想到的则是996和 ICU. 别人眼中的程序员:飞快的敲击键盘.酷炫的切换屏幕.各种看不懂的字符代码 ...

  7. opengl中的Floatbuffer和IntBuffer与java中数据的存储方式不同的解决方法,编辑一个自己的BufferUtil工具类

    opengl中的Floatbuffer和IntBuffer与java中数据的存储方式不同的解决方法,编辑一个自己的BufferUtil工具类 参考文章: (1)opengl中的Floatbuffer和 ...

  8. python测试开发自学教程-Web开发哪家强?看我用 Python 写一个颜值测试小工具

    我们知道现在有一些利用照片来测试颜值的网站或软件,其实使用 Python 就可以实现这一功能,本文我们使用 Python 来写一个颜值测试小工具. 简介 要实现颜值测试功能,大致有两种方式:一种是自己 ...

  9. python调用公共方法_common: 这是一个Python的公共工具类,集成了各种主要的python常用方法...

    common 介绍 这是一个Python的公共工具类,集成了各种主要的python常用方法. 本人是做java开发的,学习python很多情况下是把他当做一个脚本来使用,在使用的过程中,发现很多的功能 ...

最新文章

  1. winform运行时如何接受参数?(示例)
  2. ubuntu下安装、卸载软件
  3. 1到n阶乘算法的改进
  4. php 正则替换 ubb,php实现过滤UBB代码的类
  5. 机器学习里面常用知识
  6. C#递归遍历指定目录下文件和文件夹
  7. 大鱼风控笔记 2:量化风控体系的实现要求
  8. 找出两个字符串中所有共同的字符_面试中的两个字符串问题竟给我整懵了?!| 原力计划...
  9. vscode开发python使用教程_VSCode 支持Python
  10. SRS之SrsRtmpConn::publishing详解
  11. Docker破解AWVS和Nessus
  12. 计算机考试怎么做word,word怎么做弧形文字
  13. 北京口袋时尚科技公司-微店内推技术一面
  14. 如何将mov格式的视频转换mp4?
  15. P1359 租用游艇【Floyd】
  16. 有关虚拟专用局域网业务VPLS的总结
  17. A段架构设计_隽语集(IT+設計思考_1801)
  18. 用C语言判断五子棋,c语言 五子棋危险判断 求大神解释啊
  19. 步进电机与伺服电机对比
  20. java代码怎么打印松树_用JAVA画一颗树(Applet)

热门文章

  1. 智商黑洞(门萨Mensa测试)9
  2. 荣耀Magic5 Pro屏幕参数怎么样? 荣耀Magic5 Pro摄像头参数
  3. python画椭圆形_Python3 tkinter基础 Canvas create_rectangle 画虚边的矩形 create_oval 画椭圆形 圆形...
  4. 酒店订房管理系统2.0 优化版
  5. 如何分割cue+ape、cue+flac、cue+wav、cue+dts整轨音乐文件
  6. 数字化转型道阻且长?免费低代码平台也能“神助攻”
  7. 我打不了字计算机应用怎么办,键盘正常为什么打不了字 电脑键盘失灵怎么解决...
  8. VTN系列多通道振弦采集仪数据查看和参数修改
  9. 【论文复刻】企业数字化转型与资本市场表现——来自股票流动性的经验证据(2007-2021年数据)
  10. 人世间最纯净的友情只存在于孩童时代