ping2 [version 1.0]
链接: https://pan.baidu.com/s/1bcWjKbh3Gz1icXkbRdrczg?pwd=r5d9
一个可以取代微软ping的命令行工具,具有比ping更灵活的开关解析,更精准的信息反馈,引入了品率来描述一个ping质量的等级。核心层完全依据反汇编ping模仿,使用同样的API和程序流程,源码兼容单、款字符,兼容gcc,vs各类编译器。建议复制代码自行编译,以获取最佳品质的ping2.exe。
PING2.EXE (CONSOLE PING TOOL, BY LEO, VERSION 1.0)
帮助:(外链图)
演示:
摘要:
==============================================
命令行彩显PING工具,兼容PING的基础语法,并做适当扩展。
增加两个数学描述:
PINGQUA 为PING的品率,值域(0, 1.0],表示PING的品质等级,1.0为最高品质。
STD 为PING的回环时间标准差,表示回环时间的波动幅度,在100以内可算较佳。
==============================================
用法:
-------------------------------------------------------------------------
ping2 [host|IP] -t -f -a -n[count] -i[TTL] -v[TOS] -w[time out] -l[size] -d[delay]
-------------------------------------------------------------------------
-t Ping the specifed host until interrupted
-f Don't fragment
-a As IP address
-n Send count
-i Time to live
-v Type of service
-w Timeout (in milliseconds)
-l Send buffer size
-d Delayed time
-h Show help information
-------------------------------------------------------------------------
举例:
-------------------------------------------------------------------------
ping2 www.baidu.com
ping2 -n 3 www.baidu.com
ping2 www.baidu.com -n3
ping2 -n3 -l128 www.baidu.com
ping2 -i55 -fan 55 www.baidu.com -d300 -w64
ping2 -n3 -d300 -w64 www.baidu.com
...
-------------------------------------------------------------------------
备注:(关于ERRORNUM对应的状态描述)
-------------------------------------------------------------------------
IP_BUF_TOO_SMALL 11001 答复缓冲区太小
IP_DEST_NET_UNREACHABLE 11002 目标网络不可达
IP_DEST_HOST_UNREACHABLE 11003 目标主机不可达
IP_DEST_PROT_UNREACHABLE 11004 目的地的协议是遥不可及
IP_DEST_PORT_UNREACHABLE 11005 目标端口不可达
IP_NO_RESOURCES 11006 IP资源不足是可用的
IP_BAD_OPTION 11007 指定了错误的IP选项
IP_HW_ERROR 11008 一个硬件错误
IP_PACKET_TOO_BIG 11009 包太大
IP_REQ_TIMED_OUT 11010 请求超时
IP_BAD_REQ 11011 一个坏的请求
IP_BAD_ROUTE 11012 一个糟糕的路线
IP_TTL_EXPIRED_TRANSIT 11013 在传输过程中的生存时间(TTL)的过期
IP_TTL_EXPIRED_REASSEM 11014 在碎片重组过程中的生存时间过期
IP_PARAM_PROBLEM 11015 一个参数的问题
IP_SOURCE_QUENCH 11016 数据包到达太快,处理数据包可能被丢弃
IP_OPTION_TOO_BIG 11017 一个IP选项是太大了
IP_BAD_DESTINATION 11018 一个坏的目的地
IP_GENERAL_FAILURE 11050 一般故障,返回一些畸形的ICMP数据包
-------------------------------------------------------------------------
版本:
VERSION 1.0
编译:- REM UNICODE COMPILATION:
- G++ ping2.c -lWs2_32 -lIphlpapi -lUser32 -D _UNICODE -D UNICODE -municode -O2 -static
- CL ping2.c /O2 /Oy- /D "WIN32" /D "NDEBUG" /D "_CONSOLE" /D "_UNICODE" /D "UNICODE" /MD
-
- REM ANSI COMPILATION:
- G++ ping2.c -lWs2_32 -lIphlpapi -lUser32 -O2 -static
- CL ping2.c /O2 /Oy- /D "WIN32" /D "NDEBUG" /D "_CONSOLE" /MD
复制代码 源码:- /*
- CONSOLE PING TOOL, COPYRIGHT@2017~2019 BY LEO, VERSION 1.0
- PING2.EXE
- LINK WS2_32 IPHLPAPI USER32
- */
-
- #include <stdio.h>
- #include <winsock.h>
- #include <iphlpapi.h>
- #include <icmpapi.h>
- #include <tchar.h>
- #include <ctype.h>
- #include <math.h>
-
- #if defined _MSC_VER
- #pragma comment(lib,"Ws2_32.lib")
- #pragma comment(lib,"Iphlpapi.lib")
- #pragma comment(lib,"User32.lib")
- #endif
-
- #if defined(_UNICODE) || defined(UNICODE)
- #define TCHARFORMAT WCHAR
- #else
- #define TCHARFORMAT CHAR
- #endif
-
- #define DEFAULT_SEND_SIZE 32
- #define DEFAULT_COUNT 4
- #define DEFAULT_TTL 55
- #define DEFAULT_TOS 0
- #define DEFAULT_TIMEOUT 1000
- #define DEFAULT_TIMEDELAY 1000
-
- //定义帮助说明
- #define HELP_INFORMATION _T("\
- ping2 v1.0 - Console Colour Ping Tool - Copyright (C) 2017-2019 by Leo\n\
- Usage: ping2 [host|IP] -t -f -a -n[count] -i[TTL] -v[TOS] -w[time out] -l[size] -d[delay]\n\
- \n\
- General options:\n\
- -t Ping the specifed host until interrupted\n\
- -f Don't fragment\n\
- -a As IP address\n\
- -n Send count\n\
- -i Time to live\n\
- -v Type of service\n\
- -w Timeout (in milliseconds)\n\
- -l Send buffer size\n\
- -d Delayed time\n\
- -h Show help information\n\
- \n\
- Official website:\n\
- http://www.bathome.net/thread-44179-1-1.html\n")
-
- #define STR_HEAD _T("\
- ==============WELCOME YOU TO USE THE COLOR PING TOOL=============")
-
- #define STR_LINE _T("\
- =================================================================")
-
- //开关解析宏名
- #define _OPT_TEOF -1
- #define _OPT_TILL -2
- #define _OPT_TERR -3
-
- //开关解析变量
- INT OPTIND=1, OPTOPT, UNOPTIND=-1;
- TCHAR* OPTARG;
-
- //开关解析模块
- INT _tgetopt(INT nargc, TCHAR* nargv[], TCHAR* ostr)
- {
- static TCHAR* place = (TCHAR*)_T("");
- static TCHAR* lastostr = NULL;
- register TCHAR* oli;
-
- if(ostr!=lastostr)
- {
- lastostr=ostr;
- place=(TCHAR*)_T("");
- }
-
- if(!*place)
- {
- if(
- (OPTIND>=nargc) ||
- (*(place=nargv[OPTIND]) !=(TCHAR)_T('-')) ||
- (!*(++place))
- )
- {
- if(*place !=(TCHAR)_T('-') && OPTIND <nargc)
- {
- place =(TCHAR*)_T("");
- if(UNOPTIND == -1)
- {
- UNOPTIND = OPTIND++;
- return _OPT_TILL;
- }
- else
- {
- return _OPT_TERR;
- }
- }
-
- place=(TCHAR*)_T("");
- return _OPT_TEOF;
- }
- if (*place == (TCHAR)_T('-') && *(place+1) == (TCHAR)_T('\0'))
- {
- ++OPTIND;
- return _OPT_TEOF;
- }
- }
-
- if (
- (OPTOPT=*place++) == (TCHAR)_T(':') ||
- !(oli=(TCHAR*)_tcschr((TCHARFORMAT*)ostr, (TCHAR)OPTOPT))
- )
- {
- if(!*place)
- {
- ++OPTIND;
- }
- }
-
- if (oli != NULL && *(++oli) !=(TCHAR)_T(':'))
- {
- OPTARG=NULL;
- if(!*place)
- {
- ++OPTIND;
- }
- }
- else
- {
- if(*place)
- {
- OPTARG=place;
- }
- else if(nargc <= ++OPTIND)
- {
- place=(TCHAR*)_T("");
- }
- else
- {
- OPTARG=nargv[OPTIND];
- }
- place=(TCHAR*)_T("");
- ++OPTIND;
- }
- return OPTOPT;
- }
-
- //彩显函数
- INT ColorTcs(HANDLE handle_out, TCHAR* tcsTEXT1, TCHAR* tcsTEXT2, INT tcsCOLOR1, INT tcsCOLOR2)
- {
- SetConsoleTextAttribute(handle_out, tcsCOLOR1); //项色
- _ftprintf(stdout, _T("%s"), tcsTEXT1);
- SetConsoleTextAttribute(handle_out, tcsCOLOR2); //文色
- _ftprintf(stdout, _T("%s\n"), tcsTEXT2);
- return 0;
- }
-
- //转 TCHAR* 函数
- TCHAR* toTCHAR(VOID* csDATA, BOOL wcsMODE)
- {
- #if defined(_UNICODE) || defined(UNICODE)
-
- if(wcsMODE == TRUE)
- {
- return (TCHAR*)csDATA;
- }
- else
- {
- INT wLEN = MultiByteToWideChar(CP_ACP, MB_PRECOMPOSED, (CHAR*)csDATA, -1, NULL, 0);
- WCHAR* wsDATA = new WCHAR[wLEN + 1];
- MultiByteToWideChar(CP_ACP, MB_PRECOMPOSED, (CHAR*)csDATA, -1, wsDATA, wLEN);
- wsDATA[wLEN]=L'\0';
- return (TCHAR*)wsDATA;
- }
-
- #else
-
- if(wcsMODE == TRUE)
- {
- INT aLEN = WideCharToMultiByte(CP_ACP, NULL, (WCHAR*)csDATA, -1, NULL, 0, NULL, NULL);
- CHAR* asDATA = new CHAR[aLEN + 1];
- WideCharToMultiByte(CP_ACP, NULL, (WCHAR*)csDATA, -1, asDATA, aLEN, NULL, NULL);
- asDATA[aLEN] = '\0';
- return (TCHAR*)asDATA;
- }
- else
- {
- return (TCHAR*)csDATA;
- }
-
- #endif
- }
-
- //PING核心函数
- INT SendPingByUIP(HANDLE handle_out, ULONG uIPADRR, BYTE opeFLAG, INT opeCOUNT, INT opeTTL, INT opeTOS, INT opeTIMEOUT, INT opeSENDSIZE, INT opeTIMEDELAY)
- {
- HANDLE hicmpFILE = IcmpCreateFile();
- if (hicmpFILE == INVALID_HANDLE_VALUE)
- {
- //创建包文失败
- _ftprintf(stderr, _T("The ICMP header creats failed\n"));
- exit(1);
- }
-
- //填充包文头
- LPVOID sendDATA = (LPVOID)(new BYTE[opeSENDSIZE]);
- memset(sendDATA, 'E', opeSENDSIZE);
-
- DWORD replySIZE = sizeof(ICMP_ECHO_REPLY) + opeSENDSIZE;
- LPVOID replyBUFF = (LPVOID)(new BYTE[replySIZE]);
-
- //设置 IP_OPTION_INFORMATION 参数
- PIP_OPTION_INFORMATION sendOPTS = new IP_OPTION_INFORMATION;
- sendOPTS->OptionsData = 0;
- sendOPTS->OptionsSize = 0;
- sendOPTS->Ttl = opeTTL;
- sendOPTS->Tos = opeTOS;
- sendOPTS->Flags = (opeFLAG|0x02) ?IP_FLAG_DF :0;
-
- //创建一个地址容器
- PIN_ADDR replyADDR = new IN_ADDR;
-
- #if defined(_UNICODE) || defined(UNICODE)
-
- WCHAR* replyADDRW=new WCHAR[_MAX_PATH];
-
- #endif
-
- INT succeedICMP=0, failedICMP=0, minRTT=-1, maxRTT=0;
- DOUBLE totalRTT=0.0f, totalSquareRTT=0.0f;
-
- if(opeFLAG & 0x01){opeCOUNT = 65535;}
-
- for(INT i=0; i<opeCOUNT; i++)
- {
- //发送包文
- if(IcmpSendEcho(hicmpFILE, uIPADRR, sendDATA, opeSENDSIZE, sendOPTS, replyBUFF, replySIZE, opeTIMEOUT) !=0)
- {
- PICMP_ECHO_REPLY pechoREPLY =(PICMP_ECHO_REPLY)replyBUFF;
- if(pechoREPLY->Status == IP_SUCCESS)
- {
- replyADDR->S_un.S_addr = pechoREPLY->Address;
- CHAR* replyADDRA=inet_ntoa(*replyADDR);
-
- #if defined(_UNICODE) || defined(UNICODE)
-
- INT rLEN=MultiByteToWideChar(CP_ACP, MB_PRECOMPOSED, replyADDRA, -1, NULL, 0);
- MultiByteToWideChar(CP_ACP, MB_PRECOMPOSED, replyADDRA, -1, replyADDRW, rLEN);
- replyADDRW[rLEN]='\0';
- _ftprintf(stdout, _T(" REPLY FROM %s: BYTES=%u, TIME=%2ldms, TTL=%u\n"), (TCHARFORMAT*)replyADDRW, pechoREPLY->DataSize, pechoREPLY->RoundTripTime, pechoREPLY->Options.Ttl);
-
- #else
-
- _ftprintf(stdout, _T(" REPLY FROM %s: BYTES=%u, TIME=%2ldms, TTL=%u\n"), (TCHARFORMAT*)replyADDRA, pechoREPLY->DataSize, pechoREPLY->RoundTripTime, pechoREPLY->Options.Ttl);
-
- #endif
-
- //每PING间隔
- if(i+1 < opeCOUNT)
- {
- Sleep(opeTIMEDELAY);
- }
-
- //发包计数器
- succeedICMP ++;
-
- //包统计模块
- totalRTT += (DOUBLE)pechoREPLY->RoundTripTime;
- totalSquareRTT += pow((DOUBLE)pechoREPLY->RoundTripTime, 2);
- if(minRTT==-1)
- {
- minRTT =(INT)pechoREPLY->RoundTripTime;
- }
- if(minRTT > (INT)pechoREPLY->RoundTripTime)
- {
- minRTT =(INT)pechoREPLY->RoundTripTime;
- }
- if(maxRTT < (INT)pechoREPLY->RoundTripTime)
- {
- maxRTT =(INT)pechoREPLY->RoundTripTime;
- }
-
- }
- else
- {
- //丢包计数器
- failedICMP ++;
-
- SetConsoleTextAttribute(handle_out, 4|8);
- _ftprintf(stdout, _T("ERROR NUM: %u\n"), pechoREPLY->Status);
- SetConsoleTextAttribute(handle_out, 2|8);
- }
- }
- else
- {
- failedICMP ++;
- SetConsoleTextAttribute(handle_out, 4|8);
- _ftprintf(stderr, _T("THE ICMP MESSAGE SENDS FAILED\n"));
- break;
- }
- }
-
- //计算回环方差
- DOUBLE avageTIME=totalRTT/succeedICMP, sdevTIME=sqrt(totalSquareRTT/succeedICMP-pow((DOUBLE)(totalRTT/succeedICMP), 2)), pingQUA=(avageTIME==0.0f)?1:(1.0f-sdevTIME/avageTIME);
-
- //设置显示颜色
- SetConsoleTextAttribute(handle_out, 1|2|8);
-
- //统计PING质率
- _ftprintf(stdout, _T("PINGQUA : %-1.1lf\n"), pingQUA);
-
- //统计包达成率
- _ftprintf(stdout, _T("PACKETS : SEND=%d, RECEIVED=%d, LOST=%d (%2.0lf%% LOSS)\n"), succeedICMP+failedICMP, succeedICMP, failedICMP, (DOUBLE)failedICMP*100.0f/(succeedICMP+failedICMP));
-
- //显示统计信息
- _ftprintf(stdout, _T("TRIPTIME: MIN(TIME)=%dms, MAX(TIME)=%dms, E(TIME)=%dms, SDT=%.2lfms\n"), minRTT, maxRTT, (INT)avageTIME, sdevTIME);
-
- //释放句柄
- CloseHandle(hicmpFILE);
-
- //释放资源
- operator delete (sendDATA);
- operator delete (replyBUFF);
- delete sendOPTS;
- delete replyADDR;
-
- #if defined(_UNICODE) || defined(UNICODE)
-
- delete replyADDRW;
-
- #endif
-
- return 0;
- }
-
- #if defined _MSC_VER
- #else
- extern "C"
- #endif
-
- //MAIN主函数
- INT _tmain(INT argc, TCHAR** argv)
- {
- if(argc<2)
- {
- //无参数则退出
- _ftprintf(stdout, HELP_INFORMATION);
- exit(0);
- }
-
- //启动安全套接字
- WSADATA Ws;
- if(WSAStartup(MAKEWORD(2, 2), &Ws) !=0)
- {
- _ftprintf(stderr, _T("Starting the winsocket failed\n"));
- return 1;
- }
-
- //设置传入参数
- TCHAR* opeTHOST=NULL;
- BYTE opeFLAG=0x00;
- INT K=_OPT_TEOF, opeCOUNT=DEFAULT_COUNT, opeTTL=DEFAULT_TTL, opeTOS=DEFAULT_TOS, opeTIMEOUT=DEFAULT_TIMEOUT, opeSENDSIZE=DEFAULT_SEND_SIZE, opeTIMEDELAY=DEFAULT_TIMEDELAY;
-
- //开关解析
- while((K=_tgetopt(argc, argv, (TCHAR*)_T("htfan:i:v:w:l:d:HTFAN:I:V:W:L:D:"))) != _OPT_TEOF)
- {
- switch(K)
- {
- case 't':
- case 'T':
- opeFLAG |= 0x01;
- break;
-
- case 'f':
- case 'F':
- opeFLAG |= 0x02;
- break;
-
- case 'a':
- case 'A':
- ;
- opeFLAG |= 0x04;
- break;
-
- case 'n':
- case 'N':
- if(OPTARG !=NULL && _istdigit(*OPTARG) !=0)
- {
- opeCOUNT =_ttoi((TCHARFORMAT*)OPTARG);
- if(opeCOUNT > 0)
- {
- opeFLAG |= 0x08;
- break;
- }
- }
- _ftprintf(stderr, _T("The switch '-n' needs a positive number\n"));
- exit(1);
-
- case 'i':
- case 'I':
- if(OPTARG !=NULL && _istdigit(*OPTARG) !=0)
- {
- opeTTL =_ttoi((TCHARFORMAT*)OPTARG);
- if(opeTTL >= 0)
- {
-
- opeFLAG |= 0x0F;
- break;
- }
- }
- _ftprintf(stderr, _T("The switch '-i' needs a positive number\n"));
- exit(1);
-
- case 'v':
- case 'V':
- if(OPTARG !=NULL && _istdigit(*OPTARG) !=0)
- {
- opeTOS =_ttoi((TCHARFORMAT*)OPTARG);
- if(opeTOS >= 0)
- {
- opeFLAG |= 0x10;
- break;
- }
- }
- _ftprintf(stderr, _T("The switch '-v' needs a positive number\n"));
- exit(1);
-
- case 'w':
- case 'W':
- if(OPTARG !=NULL && _istdigit(*OPTARG) !=0)
- {
- opeTIMEOUT =_ttoi((TCHARFORMAT*)OPTARG);
- if(opeTIMEOUT >= 0)
- {
- opeFLAG |= 0x20;
- break;
- }
- }
- _ftprintf(stderr, _T("The switch '-w' needs a positive number\n"));
- exit(1);
-
- case 'l':
- case 'L':
- if(OPTARG !=NULL && _istdigit(*OPTARG) !=0)
- {
- opeSENDSIZE =_ttoi((TCHARFORMAT*)OPTARG);
- if(0<= opeSENDSIZE && opeSENDSIZE <=65500)
- {
- opeFLAG |= 0x40;
- break;
- }
- }
- _ftprintf(stderr, _T("The switch '-l' needs a number less 65KB\n"));
- exit(1);
-
- case 'd':
- case 'D':
- if(OPTARG !=NULL && _istdigit(*OPTARG) !=0)
- {
- opeTIMEDELAY =_ttoi((TCHARFORMAT*)OPTARG);
- if(opeTIMEDELAY >= 0)
- {
- opeFLAG |= 0x80;
- break;
- }
- }
- _ftprintf(stderr, _T("The switch '-d' needs a positive number\n"));
- exit(1);
-
- case 'h':
- case 'H':
- _ftprintf(stdout, HELP_INFORMATION);
- exit(0);
-
- case _OPT_TILL:
- //第一个无选项的参数识别为主机名
- opeTHOST = argv[UNOPTIND];
- break;
-
- case _OPT_TERR:
- _ftprintf(stderr, _T("Extra parameters \"%s\"\n"), argv[OPTIND]);
- exit(1);
-
- default:
- _ftprintf(stderr, _T("Unknown switch '-%c'\n"), K);
- exit(1);
-
- }
- }
-
- //无主机名,强制退出
- if(opeTHOST == NULL)
- {
- _ftprintf(stderr, _T("Needs host name or IP address\n"));
- exit(1);
- }
-
- #if defined(_UNICODE) || defined(UNICODE)
-
- INT thostLEN = WideCharToMultiByte(CP_ACP, NULL, opeTHOST, -1, NULL, 0, NULL, NULL);
- CHAR* opeHOSTNAME = new CHAR[thostLEN + 1];
- WideCharToMultiByte(CP_ACP, NULL, opeTHOST, -1, opeHOSTNAME, thostLEN, NULL, NULL);
- opeHOSTNAME[thostLEN] = '\0';
-
- #else
-
- CHAR* opeHOSTNAME = opeTHOST;
-
- #endif
-
- //获取主机HOST
- PHOSTENT pHOSTENT = gethostbyname(opeHOSTNAME);
- ULONG uIPADRR = INADDR_NONE;
-
- //尝试作为IP地址解析
- if (! pHOSTENT)
- {
- uIPADRR = inet_addr(opeHOSTNAME);
- //识别失败,非正常主机名
- if (uIPADRR == INADDR_NONE)
- {
- _ftprintf(stderr, _T("Not a correct hostname\n"), K);
- exit(1);
- }
- }
-
- //获取UIP值
- PIN_ADDR pINADRR = (PIN_ADDR)pHOSTENT->h_addr;
- if((uIPADRR=pINADRR->S_un.S_addr) == INADDR_NONE)
- {
- //获取UIP失败,执行退出
- _ftprintf(stderr, _T("Get UIP failed\n"), K);
- exit(1);
- }
-
- //获取控制台输出句柄
- HANDLE handle_out=GetStdHandle(STD_OUTPUT_HANDLE);
-
- //获取控制台初始配色
- WORD orgCOLOR;
- CONSOLE_SCREEN_BUFFER_INFO buffINFO;
- GetConsoleScreenBufferInfo(handle_out, &buffINFO);
- orgCOLOR=buffINFO.wAttributes;
-
- //显示题头
- ColorTcs(handle_out, (TCHARFORMAT*)STR_HEAD, (TCHARFORMAT*)_T(""), 4|8, 2|4|8);
- //显示主机名
- ColorTcs(handle_out, (TCHARFORMAT*)_T("<HOST-NAME> "), _tcsupr(toTCHAR(pHOSTENT->h_name, FALSE)), 4|8, 1|2|8);
-
- //显示主机别名
- INT iINDEX = 0;
- while(pHOSTENT->h_aliases[iINDEX])
- {
- ColorTcs(handle_out, (TCHARFORMAT*)_T("<ALIA-NAME> "), _tcsupr(toTCHAR(pHOSTENT->h_aliases[iINDEX], FALSE)), 4|8, 1|2|8);
- iINDEX ++;
- }
- //显示题尾
- ColorTcs(handle_out, (TCHARFORMAT*)STR_LINE, (TCHARFORMAT*)_T(""), 4|8, 2|8);
-
- //调用 PING 核心函数
- INT retVALUE = SendPingByUIP(handle_out, uIPADRR, opeFLAG, opeCOUNT, opeTTL, opeTOS, opeTIMEOUT, opeSENDSIZE, opeTIMEDELAY);
-
- #if defined(_UNICODE) || defined(UNICODE)
-
- //释放内存
- delete opeHOSTNAME;
-
- #endif
-
- //还原字体颜色
- SetConsoleTextAttribute(handle_out, orgCOLOR);
-
- //关闭安全套接字
- WSACleanup();
-
- return retVALUE;
- }
复制代码
|