收藏一个Ping的小工具类,可用于网络中检测目的设备是否在线
记不起在哪个项目中需要做一个检查设备在线状态的功能,可当时又没有设备的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的小工具类,可用于网络中检测目的设备是否在线相关推荐
- aspose 转pdf表格大小乱了_自己写了一个小工具类:pdf转word,没有页数和大小限制,保真!...
昨天下午遇到一个问题,想把一个比较大的pdf转化为word,结果使用了各种工具都收费.想着干脆写一个小工具吧,一开始使用的python等等试了好几个网上的代码,结果全都失真.于是乎不得不花了一下午自己 ...
- 一个Android下ping的简单工具类
这是一个自己写的Android下的ping的简单工具类,主要是通过ping获取到返回字符串之后截取信息得到自己想要的数据.不多说,上源码 import java.io.BufferedReader; ...
- python打字_使用Python制作一个打字训练小工具
一.写在前面 说道程序员,你会想到什么呢?有人认为程序员象征着高薪,有人认为程序员都是死肥宅,还有人想到的则是996和 ICU. 别人眼中的程序员:飞快的敲击键盘.酷炫的切换屏幕.各种看不懂的字符代码 ...
- 封装一个常用的js工具类
/*** @author:水痕* @timer:2016-07-28* @email:332904234@qq.com* @version:1.0* @title:封装一个自己常用的工具类js* @n ...
- java web 项目 常用 小工具类 ~~~~
java web 项目 常用 小工具类 ~~~~ 一 .DateUtil 日期工具类 package com.devframe.common.util;import java.text.Simple ...
- python 编写实用小工具-使用Python制作一个打字训练小工具
一.写在前面 说道程序员,你会想到什么呢?有人认为程序员象征着高薪,有人认为程序员都是死肥宅,还有人想到的则是996和 ICU. 别人眼中的程序员:飞快的敲击键盘.酷炫的切换屏幕.各种看不懂的字符代码 ...
- opengl中的Floatbuffer和IntBuffer与java中数据的存储方式不同的解决方法,编辑一个自己的BufferUtil工具类
opengl中的Floatbuffer和IntBuffer与java中数据的存储方式不同的解决方法,编辑一个自己的BufferUtil工具类 参考文章: (1)opengl中的Floatbuffer和 ...
- python测试开发自学教程-Web开发哪家强?看我用 Python 写一个颜值测试小工具
我们知道现在有一些利用照片来测试颜值的网站或软件,其实使用 Python 就可以实现这一功能,本文我们使用 Python 来写一个颜值测试小工具. 简介 要实现颜值测试功能,大致有两种方式:一种是自己 ...
- python调用公共方法_common: 这是一个Python的公共工具类,集成了各种主要的python常用方法...
common 介绍 这是一个Python的公共工具类,集成了各种主要的python常用方法. 本人是做java开发的,学习python很多情况下是把他当做一个脚本来使用,在使用的过程中,发现很多的功能 ...
最新文章
- winform运行时如何接受参数?(示例)
- ubuntu下安装、卸载软件
- 1到n阶乘算法的改进
- php 正则替换 ubb,php实现过滤UBB代码的类
- 机器学习里面常用知识
- C#递归遍历指定目录下文件和文件夹
- 大鱼风控笔记 2:量化风控体系的实现要求
- 找出两个字符串中所有共同的字符_面试中的两个字符串问题竟给我整懵了?!| 原力计划...
- vscode开发python使用教程_VSCode 支持Python
- SRS之SrsRtmpConn::publishing详解
- Docker破解AWVS和Nessus
- 计算机考试怎么做word,word怎么做弧形文字
- 北京口袋时尚科技公司-微店内推技术一面
- 如何将mov格式的视频转换mp4?
- P1359 租用游艇【Floyd】
- 有关虚拟专用局域网业务VPLS的总结
- A段架构设计_隽语集(IT+設計思考_1801)
- 用C语言判断五子棋,c语言 五子棋危险判断 求大神解释啊
- 步进电机与伺服电机对比
- java代码怎么打印松树_用JAVA画一颗树(Applet)
热门文章
- 智商黑洞(门萨Mensa测试)9
- 荣耀Magic5 Pro屏幕参数怎么样? 荣耀Magic5 Pro摄像头参数
- python画椭圆形_Python3 tkinter基础 Canvas create_rectangle 画虚边的矩形 create_oval 画椭圆形 圆形...
- 酒店订房管理系统2.0 优化版
- 如何分割cue+ape、cue+flac、cue+wav、cue+dts整轨音乐文件
- 数字化转型道阻且长?免费低代码平台也能“神助攻”
- 我打不了字计算机应用怎么办,键盘正常为什么打不了字 电脑键盘失灵怎么解决...
- VTN系列多通道振弦采集仪数据查看和参数修改
- 【论文复刻】企业数字化转型与资本市场表现——来自股票流动性的经验证据(2007-2021年数据)
- 人世间最纯净的友情只存在于孩童时代