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
编译: | | | 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" /MDCOPY |
源码: | | | | | | | | | | | | | #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* 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 | | } | | | | | | 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]); | | | | | | 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 | | | | | | 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); | | | | | | _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 | | | | | | 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 | | | | | | PHOSTENT pHOSTENT = gethostbyname(opeHOSTNAME); | | ULONG uIPADRR = INADDR_NONE; | | | | | | if (! pHOSTENT) | | { | | uIPADRR = inet_addr(opeHOSTNAME); | | | | if (uIPADRR == INADDR_NONE) | | { | | _ftprintf(stderr, _T("Not a correct hostname\n"), K); | | exit(1); | | } | | } | | | | | | PIN_ADDR pINADRR = (PIN_ADDR)pHOSTENT->h_addr; | | if((uIPADRR=pINADRR->S_un.S_addr) == INADDR_NONE) | | { | | | | _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); | | | | | | 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; | | }COPY |
|