c++builder ping_c++实现ping功能(转)

#pragma once

//在默认windows.h会包含winsock.h,当你包含winsock2.h就会冲突,因此在包含windows.h前需要定义一个宏,#define WIN32_LEAN_AND_MEAN ;去除winsock.h

//要么将#include 放在#include前面或者直接去掉#include

#include

#pragma comment(lib, "WS2_32")    // 链接到WS2_32.lib

#define DEF_PACKET_SIZE 32

#define ECHO_REQUEST 8

#define ECHO_REPLY 0

struct IPHeader

{

BYTE m_byVerHLen; //4位版本+4位首部长度

BYTE m_byTOS; //服务类型

USHORT m_usTotalLen; //总长度

USHORT m_usID; //标识

USHORT m_usFlagFragOffset; //3位标志+13位片偏移

BYTE m_byTTL; //TTL

BYTE m_byProtocol; //协议

USHORT m_usHChecksum; //首部检验和

ULONG m_ulSrcIP; //源IP地址

ULONG m_ulDestIP; //目的IP地址

};

struct ICMPHeader

{

BYTE m_byType; //类型

BYTE m_byCode; //代码

USHORT m_usChecksum; //检验和

USHORT m_usID; //标识符

USHORT m_usSeq; //序号

ULONG m_ulTimeStamp; //时间戳(非标准ICMP头部)

};

struct PingReply

{

USHORT m_usSeq;

DWORD m_dwRoundTripTime;

DWORD m_dwBytes;

DWORD m_dwTTL;

};

class CPing

{

public:

CPing();

~CPing();

BOOL Ping(DWORD dwDestIP, PingReply *pPingReply = NULL, DWORD dwTimeout = 2000);

BOOL Ping(char *szDestIP, PingReply *pPingReply = NULL, DWORD dwTimeout = 2000);

private:

BOOL PingCore(DWORD dwDestIP, PingReply *pPingReply, DWORD dwTimeout);

USHORT CalCheckSum(USHORT *pBuffer, int nSize);

ULONG GetTickCountCalibrate();

private:

SOCKET m_sockRaw;

WSAEVENT m_event;

USHORT m_usCurrentProcID;

char *m_szICMPData;

BOOL m_bIsInitSucc;

private:

static USHORT s_usPacketSeq;

};

实现:

#include "ping.h"

#include

USHORT CPing::s_usPacketSeq = 0;

CPing::CPing() :m_szICMPData(NULL),m_bIsInitSucc(FALSE)

{

WSADATA WSAData;

//WSAStartup(MAKEWORD(2, 2), &WSAData);

if (WSAStartup(MAKEWORD(1, 1), &WSAData) != 0)

{

/*如果初始化不成功则报错,GetLastError()返回发生的错误信息*/

printf("WSAStartup() failed: %d\n", GetLastError());

return;

}

m_event = WSACreateEvent();

m_usCurrentProcID = (USHORT)GetCurrentProcessId();

//setsockopt(m_sockRaw);

/*if ((m_sockRaw = WSASocket(AF_INET, SOCK_RAW, IPPROTO_ICMP, NULL, 0, 0)) != SOCKET_ERROR)

{

WSAEventSelect(m_sockRaw, m_event, FD_READ);

m_bIsInitSucc = TRUE;

m_szICMPData = (char*)malloc(DEF_PACKET_SIZE + sizeof(ICMPHeader));

if (m_szICMPData == NULL)

{

m_bIsInitSucc = FALSE;

}

}*/

m_sockRaw = WSASocket(AF_INET, SOCK_RAW, IPPROTO_ICMP, NULL, 0, 0);

if (m_sockRaw == INVALID_SOCKET)

{

std::cerr << "WSASocket() failed:" << WSAGetLastError ()<< std::endl;  //10013 以一种访问权限不允许的方式做了一个访问套接字的尝试。

}

else

{

WSAEventSelect(m_sockRaw, m_event, FD_READ);

m_bIsInitSucc = TRUE;

m_szICMPData = (char*)malloc(DEF_PACKET_SIZE + sizeof(ICMPHeader));

if (m_szICMPData == NULL)

{

m_bIsInitSucc = FALSE;

}

}

}

CPing::~CPing()

{

WSACleanup();

if (NULL != m_szICMPData)

{

free(m_szICMPData);

m_szICMPData = NULL;

}

}

BOOL CPing::Ping(DWORD dwDestIP, PingReply *pPingReply, DWORD dwTimeout)

{

return PingCore(dwDestIP, pPingReply, dwTimeout);

}

BOOL CPing::Ping(char *szDestIP, PingReply *pPingReply, DWORD dwTimeout)

{

if (NULL != szDestIP)

{

return PingCore(inet_addr(szDestIP), pPingReply, dwTimeout);

}

return FALSE;

}

BOOL CPing::PingCore(DWORD dwDestIP, PingReply *pPingReply, DWORD dwTimeout)

{

//判断初始化是否成功

if (!m_bIsInitSucc)

{

return FALSE;

}

//配置SOCKET

sockaddr_in sockaddrDest;

sockaddrDest.sin_family = AF_INET;

sockaddrDest.sin_addr.s_addr = dwDestIP;

int nSockaddrDestSize = sizeof(sockaddrDest);

//构建ICMP包

int nICMPDataSize = DEF_PACKET_SIZE + sizeof(ICMPHeader);

ULONG ulSendTimestamp = GetTickCountCalibrate();

USHORT usSeq = ++s_usPacketSeq;

memset(m_szICMPData, 0, nICMPDataSize);

ICMPHeader *pICMPHeader = (ICMPHeader*)m_szICMPData;

pICMPHeader->m_byType = ECHO_REQUEST;

pICMPHeader->m_byCode = 0;

pICMPHeader->m_usID = m_usCurrentProcID;

pICMPHeader->m_usSeq = usSeq;

pICMPHeader->m_ulTimeStamp = ulSendTimestamp;

pICMPHeader->m_usChecksum = CalCheckSum((USHORT*)m_szICMPData, nICMPDataSize);

//发送ICMP报文

if (sendto(m_sockRaw, m_szICMPData, nICMPDataSize, 0, (struct sockaddr*)&sockaddrDest, nSockaddrDestSize) == SOCKET_ERROR)

{

return FALSE;

}

//判断是否需要接收相应报文

if (pPingReply == NULL)

{

return TRUE;

}

char recvbuf[256] = { "\0" };

while (TRUE)

{

//接收响应报文

if (WSAWaitForMultipleEvents(1, &m_event, FALSE, 100, FALSE) != WSA_WAIT_TIMEOUT)

{

WSANETWORKEVENTS netEvent;

WSAEnumNetworkEvents(m_sockRaw, m_event, &netEvent);

if (netEvent.lNetworkEvents & FD_READ)

{

ULONG nRecvTimestamp = GetTickCountCalibrate();

int nPacketSize = recvfrom(m_sockRaw, recvbuf, 256, 0, (struct sockaddr*)&sockaddrDest, &nSockaddrDestSize);

if (nPacketSize != SOCKET_ERROR)

{

IPHeader *pIPHeader = (IPHeader*)recvbuf;

USHORT usIPHeaderLen = (USHORT)((pIPHeader->m_byVerHLen & 0x0f) * 4);

ICMPHeader *pICMPHeader = (ICMPHeader*)(recvbuf + usIPHeaderLen);

if (pICMPHeader->m_usID == m_usCurrentProcID //是当前进程发出的报文

&& pICMPHeader->m_byType == ECHO_REPLY //是ICMP响应报文

&& pICMPHeader->m_usSeq == usSeq //是本次请求报文的响应报文

)

{

pPingReply->m_usSeq = usSeq;

pPingReply->m_dwRoundTripTime = nRecvTimestamp - pICMPHeader->m_ulTimeStamp;

pPingReply->m_dwBytes = nPacketSize - usIPHeaderLen - sizeof(ICMPHeader);

pPingReply->m_dwTTL = pIPHeader->m_byTTL;

return TRUE;

}

}

}

}

//超时

if (GetTickCountCalibrate() - ulSendTimestamp >= dwTimeout)

{

return FALSE;

}

}

}

USHORT CPing::CalCheckSum(USHORT *pBuffer, int nSize)

{

unsigned long ulCheckSum = 0;

while (nSize > 1)

{

ulCheckSum += *pBuffer++;

nSize -= sizeof(USHORT);

}

if (nSize)

{

ulCheckSum += *(UCHAR*)pBuffer;

}

ulCheckSum = (ulCheckSum >> 16) + (ulCheckSum & 0xffff);

ulCheckSum += (ulCheckSum >> 16);

return (USHORT)(~ulCheckSum);

}

ULONG CPing::GetTickCountCalibrate()

{

static ULONG s_ulFirstCallTick = 0;

static LONGLONG s_ullFirstCallTickMS = 0;

SYSTEMTIME systemtime;

FILETIME filetime;

GetLocalTime(&systemtime);

SystemTimeToFileTime(&systemtime, &filetime);

LARGE_INTEGER liCurrentTime;

liCurrentTime.HighPart = filetime.dwHighDateTime;

liCurrentTime.LowPart = filetime.dwLowDateTime;

LONGLONG llCurrentTimeMS = liCurrentTime.QuadPart / 10000;

if (s_ulFirstCallTick == 0)

{

s_ulFirstCallTick = GetTickCount();

}

if (s_ullFirstCallTickMS == 0)

{

s_ullFirstCallTickMS = llCurrentTimeMS;

}

return s_ulFirstCallTick + (ULONG)(llCurrentTimeMS - s_ullFirstCallTickMS);

}

main.cpp

#include

#include

#include "ping.h"

int main(void)

{

CPing objPing;

char *szDestIP = "127.0.0.1";

PingReply reply;

printf("Pinging %s with %d bytes of data:\n", szDestIP, DEF_PACKET_SIZE);

while (TRUE)

{

objPing.Ping(szDestIP, &reply);

printf("Reply from %s: bytes=%d time=%ldms TTL=%ld\n", szDestIP, reply.m_dwBytes, reply.m_dwRoundTripTime, reply.m_dwTTL);

Sleep(500);

}

return 0;

}

域名解析实际IP地址:

转载:https://www.cnblogs.com/ranjiewen/p/5704627.html

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值