ping.rar

  • greathelen
    了解作者
  • C/C++
    开发工具
  • 3KB
    文件大小
  • rar
    文件格式
  • 0
    收藏次数
  • 10 积分
    下载积分
  • 1
    下载次数
  • 2020-02-17 11:30
    上传日期
应用C语言,编程实现Ping命令,简单程序
ping.rar
  • ping.cpp
    10.6KB
内容介绍
#include "pch.h" #include <WinSock2.h> #include <iostream> #include <windows.h> #include <stdio.h> #include "Ws2tcpip.h" #pragma comment(lib,"WS2_32.lib") #pragma comment(lib,"Iphlpapi.lib") class CInitSock { public: CInitSock(BYTE minorVer = 2, BYTE majorVer = 2) { // 初始化WS2_32.dll WSADATA wsaData; WORD sockVersion = MAKEWORD(minorVer, majorVer); if (::WSAStartup(sockVersion, &wsaData) != 0) { exit(0); } } ~CInitSock() { ::WSACleanup(); } }; CInitSock theSock; struct Para { int icmp_size = 32; int allcnt = 4; char szDestIp[16] = "10.0.0.55"; int TTL = 0; int TOS = 0x00; int DLY = 1000; }; BOOL SetTimeout(SOCKET s, int nTime, BOOL bRecv) { int ret = ::setsockopt(s, SOL_SOCKET, bRecv ? SO_RCVTIMEO : SO_SNDTIMEO, (char*)&nTime, sizeof(nTime)); return ret != SOCKET_ERROR; }; typedef struct icmp_hdr { unsigned char icmp_type; //消息类型 unsigned char icmp_code; //代码 unsigned short icmp_checksum; //校验和 //以下为回显头 unsigned short icmp_id; //唯一标识的ID号 unsigned short icmp_sequence; //序列号 unsigned long icmp_timestamp; //时间戳 }ICMP_HDR, *PICMP_HDR; typedef struct ncount { int Sentnum = 0; int Recvnum = 0; int maxnum = 0; int minnum = 1000; // int allcnt = 4; int alltime = 0; }ncount; typedef struct _IPHeader { UCHAR iphVerLen; UCHAR ipTOS; USHORT iplength; USHORT ipID; USHORT ipFlags; UCHAR ipTTL; UCHAR ipProtocol; USHORT ipChecksum; ULONG ipSource; ULONG ipDestination; }IPHeader,*PIPHeader; BOOL SetTTL(SOCKET s, char nValue) { int ret = ::setsockopt(s, IPPROTO_IP, IP_TTL, (char*)&nValue, sizeof(nValue)); return (ret != SOCKET_ERROR); } 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); } void Route_trace(Para x) { int icmp_size = x.icmp_size; int allcnt = x.allcnt; char recvBuf[1024] = { 0 }; // 创建用于接收ICMP封包的原始套节字,绑定到本地端口 SOCKET sRaw = ::socket(AF_INET, SOCK_RAW, IPPROTO_ICMP); sockaddr_in in; in.sin_family = AF_INET; in.sin_port = 0; in.sin_addr.S_un.S_addr = INADDR_ANY; if (::bind(sRaw, (sockaddr*)&in, sizeof(in)) == SOCKET_ERROR) { printf(" bind() failed \n"); return; } SetTimeout(sRaw, 1000, TRUE); // 创建用于发送UDP封包的套节字 SOCKET sSend = ::socket(AF_INET, SOCK_DGRAM, IPPROTO_IP); SOCKADDR_IN destAddr; destAddr.sin_family = AF_INET; destAddr.sin_port = ::htons(0); destAddr.sin_addr.S_un.S_addr = ::inet_addr(x.szDestIp); char ICMPbuf[sizeof(ICMP_HDR) + 1024]; ICMP_HDR* pIcmp = (ICMP_HDR*)ICMPbuf; pIcmp->icmp_type = 8; pIcmp->icmp_code = 0; pIcmp->icmp_id = (USHORT)::GetCurrentProcessId(); pIcmp->icmp_checksum = 0; pIcmp->icmp_sequence = 0; memset(&ICMPbuf[sizeof(ICMP_HDR)], 'E', 32); int nTTL = 1; int nRet = 0; ICMP_HDR *pICMPHdr; int nTick = 0; SOCKADDR_IN recvAddr; do { // 设置UDP封包的TTL值 if (SetTTL(sRaw, nTTL) == 0) { return; } nTick = ::GetTickCount(); pIcmp->icmp_checksum = 0; pIcmp->icmp_timestamp = nTick; pIcmp->icmp_sequence = nTTL; pIcmp->icmp_checksum = checksum((USHORT*)ICMPbuf, sizeof(ICMP_HDR) + 32); // 发送这个UDP封包 nRet = ::sendto(sRaw, ICMPbuf, 44, 0, (sockaddr*)&destAddr, sizeof(destAddr)); // nRet = ::sendto(sRaw, buff, sizeof(ICMP_HDR) + icmp_size, 0, (SOCKADDR *)&dest, sizeof(dest)); if (nRet == SOCKET_ERROR) { printf(" sendto() failed \n"); break; } // 等待接收路由器返回的ICMP报文 int nLen = sizeof(recvAddr); nRet = ::recvfrom(sRaw, recvBuf, 1024, 0, (sockaddr*)&recvAddr, &nLen); if (nRet == SOCKET_ERROR) { if (::WSAGetLastError() == WSAETIMEDOUT) { printf(" time out \n"); continue; } else { printf(" recvfrom() failed \n"); break; } } // 解析接收到的ICMP数据 pICMPHdr = (ICMP_HDR*)&recvBuf[20]; // sizeof(IPHeader) //if (pICMPHdr->icmp_type != 11 && pICMPHdr->icmp_type != 3 && pICMPHdr->icmp_code != 3) //{ // printf(" Unexpected Type: %d , code: %d \n", // pICMPHdr->icmp_type, pICMPHdr->icmp_code); //} //else char *szIP = ::inet_ntoa(recvAddr.sin_addr); printf(" No%drouter,IP adress:%s \n", nTTL, szIP); printf(" Time:%dms \n", ::GetTickCount() - nTick); if (destAddr.sin_addr.S_un.S_addr == recvAddr.sin_addr.S_un.S_addr) { printf("Target Arrivable\n"); break; } printf("//------------------------------------// \n"); } while (nTTL++ < 20); ::closesocket(sRaw); ::closesocket(sSend); } int pinging(Para x){ int icmp_size = x.icmp_size; int allcnt = x.allcnt; std::cout << "Pinging " <<x.szDestIp << "...\n"; ncount cnt; SOCKET sRaw = ::socket(AF_INET, SOCK_RAW, IPPROTO_ICMP); //设置接收超时 SetTimeout(sRaw, x.DLY , TRUE); //设置目的地址 SOCKADDR_IN dest; dest.sin_family = AF_INET; dest.sin_port = htons(0); dest.sin_addr.S_un.S_addr = inet_addr(x.szDestIp); //创建ICMP封包 char buff[sizeof(ICMP_HDR) + 1024]; ICMP_HDR* pIcmp = (ICMP_HDR*)buff; //填写ICMP封包数据 pIcmp->icmp_type = 8; pIcmp->icmp_code = 0; pIcmp->icmp_id = (USHORT)::GetCurrentProcessId(); pIcmp->icmp_checksum = 0; pIcmp->icmp_sequence = 0; //填充数据部分 memset(&buff[sizeof(ICMP_HDR)], 'E', icmp_size); //开始发送和接收 USHORT nSeq = 0; char recvBuf[1024]; SOCKADDR_IN from; int nLen = sizeof(from); cnt.Recvnum = 0; cnt.Sentnum = 0; while (TRUE) { int nRet; if (cnt.Sentnum++ == allcnt) { break; } pIcmp->icmp_checksum = 0; pIcmp->icmp_timestamp = ::GetTickCount(); pIcmp->icmp_sequence = nSeq++; pIcmp->icmp_checksum = checksum((USHORT*)buff, sizeof(ICMP_HDR) + icmp_size); if (x.TTL) { SetTTL(sRaw, x.TTL); } if (x.TOS) { if (setsockopt(sRaw, IPPROTO_IP, IP_TOS, (char*)&x.TOS, sizeof(x.TOS)) < 0) perror("setsockopt(IP_TOS) failed:"); } nRet = ::sendto(sRaw, buff, sizeof(ICMP_HDR) + icmp_size, 0, (SOCKADDR *)&dest, sizeof(dest)); if (nRet == SOCKET_ERROR) { std::cout << "sendto " << x.szDestIp << " failed: " << ::WSAGetLastError() << "\n"; continue; } nRet = ::recvfrom(sRaw, recvBuf, 1024, 0, (sockaddr*)&from, &nLen); if (nRet == SOCKET_ERROR) { if (::WSAGetLastError() == WSAETIMEDOUT) { printf("timed out\n"); continue; } printf("recvfrom() failed: %d\n", ::WSAGetLastError()); return -1; } //解析接受到的ICMP封包 if (nRet < sizeof(IPHeader) + sizeof(ICMP_HDR)) { printf("Too few bytes from %s /n", ::inet_ntoa(from.sin_addr)); } IPHeader* pRecvIP = (IPHeader*)(recvBuf); //去掉接收数据中的IP头(+sizeof(IPHeader)) ICMP_HDR* pRecvIcmp = (ICMP_HDR*)(recvBuf + sizeof(IPHeader)); if (pRecvIcmp->icmp_type != 0)//回显 { printf("nonecho type %d recvd \n", pRecvIcmp->icmp_type); return -1; } if (pRecvIcmp->icmp_id != ::GetCurrentProcessId()) { printf("someone slse's packet!\n"); return -1; } int nTick = ::GetTickCount(); int time_cost = nTick - pRecvIcmp->icmp_timestamp; printf("%d bytes from %s:", nRet, inet_ntoa(from.sin_addr)); printf("icmp_seq = %d."
评论
    相关推荐