Ping_C++实现_20090102

 

头文件:Ping.h

#ifndef __checkmachine__
#define __checkmachine__

#include <winsock.h>
#include <windows.h>

typedef unsigned short ushort;
typedef unsigned int uint;
typedef unsigned char uchar;

typedef struct icmp_hdr
{
uchar type;   //1
uchar code;   //1
ushort checksum; //2

//other data
ushort id;    //2
ushort sequence; //2
uint timestamp; //4
}ICMP;      //12B

#define BUFLEN   0//32
#define IPHEADLEN 20
#define TIMEOUT   1
#define IPLEN   16

class kyPing
{
SOCKET   mSocket;
SOCKADDR_IN mDest;

ushort   mProcessId;        //icmp's sequence
char   mSendBuf[sizeof(ICMP) + BUFLEN]; //send icmp data
//char   mRecvBuf[sizeof(ICMP) + BUFLEN]; //暂时做法
char   mRecvBuf[1024];
uint   mRecvLen;

HANDLE   mLock;

public:
kyPing();
~kyPing();
//void run();

bool Init();
bool PingSend(char* ip, ushort seq = 0);
bool PingRecv();

private:
void PackSendBuf(uint seq);
bool UnPackRecvBuf();
ushort CheckICMPSum(ushort* buf, int size);
bool SetTimeout(int nTime, bool bRecv);
};

#endif

源文件:Ping.cpp

#include "Check.h"
#include <string.h>
#include <stdio.h>

kyPing::kyPing()
{
memset(&mDest, 0, sizeof(SOCKADDR_IN));
mDest.sin_family = AF_INET;
mRecvLen = 0;
// if(ip != NULL || (strlen(ip) + 1) < IPLEN) //不进行检查,要确保正确
// {
//   mDest.sin_addr.S_un.S_addr = inet_addr(ip);
// }

}

kyPing::~kyPing()
{
closesocket(mSocket);
mSocket = 0;
WSACleanup();
}

bool kyPing::Init()
{
WSADATA wsaData;
if(::WSAStartup(MAKEWORD(2, 2), &wsaData) != 0)
{
   return false;
}

//raw socket
mSocket   = ::socket(AF_INET, SOCK_RAW, IPPROTO_ICMP);
if(mSocket == INVALID_SOCKET)
{
   return false;
}
SetTimeout(TIMEOUT * 1000, true);

mProcessId = (ushort)::GetCurrentProcessId();

//init buffer info
memset(mSendBuf, 0, sizeof(mSendBuf));
ICMP* icmp = (ICMP*)mSendBuf;
icmp->type = 8;          //require icmp return show
icmp->id = mProcessId;
if(BUFLEN > 0)
   memset(&mSendBuf[sizeof(ICMP)], 1, BUFLEN);   //data

mLock = CreateMutex(NULL, false, NULL);
return true;
}

bool kyPing::PingSend(char* ip, ushort seq)
{
int len = sizeof(mSendBuf);

::WaitForSingleObject(mLock, INFINITE);

mDest.sin_addr.S_un.S_addr = inet_addr(ip); //没有进行ip检查,要确保正确
PackSendBuf(seq);

if(len != ::sendto(mSocket, mSendBuf, len, 0, (SOCKADDR*)&mDest, sizeof(SOCKADDR_IN)))
{
   printf("sendtto error: %d!/n", WSAGetLastError());
   ReleaseMutex(mLock);
   return false;
}

ReleaseMutex(mLock);

return true;
}

bool kyPing::PingRecv()
{
SOCKADDR_IN from;
int len = sizeof(SOCKADDR_IN);

::WaitForSingleObject(mLock, INFINITE);

memset(mRecvBuf, 0, sizeof(mRecvBuf));
mRecvLen = ::recvfrom(mSocket, mRecvBuf, sizeof(mRecvBuf), 0, (sockaddr*)&from, &len);
if(SOCKET_ERROR != mRecvLen)
{
   if(UnPackRecvBuf())
   {
    ReleaseMutex(mLock);
    return true;
   }
}

ReleaseMutex(mLock);

printf("recvfrom error: %d!/n", WSAGetLastError());
return false;
}

//contruct icmp_head data
void kyPing::PackSendBuf(uint seq)
{
ICMP* icmp = (ICMP*)mSendBuf;

icmp->checksum = 0;
icmp->sequence = seq;     //***** can use to array[ip]'s no
icmp->timestamp = ::GetTickCount();
icmp->checksum = CheckICMPSum((ushort*)mSendBuf, sizeof(mSendBuf));
}

bool kyPing::UnPackRecvBuf()
{
if(mRecvLen < (sizeof(ICMP) + IPHEADLEN)) //len too smaller, drop
{
   printf("error: recv data too lower!/n");
   return false;
}

ICMP* icmp = (ICMP*)&mRecvBuf[IPHEADLEN];
if(icmp->id != mProcessId)      //other packet
{
   printf("error: other packet!/n");
   return false;
}

if(icmp->type == 0)
{
   //mStatus = 1;
  
   //calculate spending time, test
   printf("recv %dbyte, spend time: %dms/n", mRecvLen, ::GetTickCount() - icmp->timestamp);
}

return true;
}

ushort kyPing::CheckICMPSum(ushort* buf, int size)
{
uint cksum = 0;

while(size > 1)
{
   cksum += *buf++;
   size -= sizeof(USHORT);
}

if(size)
{
   cksum += *(uchar*)buf;
}

cksum = (cksum >> 16) + (cksum & 0xffff);
cksum += (cksum >> 16);
return (ushort)(~cksum);
}

bool kyPing::SetTimeout(int nTime, bool bRecv)
{
int ret = ::setsockopt(mSocket, SOL_SOCKET,
   bRecv ? SO_RCVTIMEO : SO_SNDTIMEO, (char*)&nTime, sizeof(nTime));
return ret != SOCKET_ERROR;
}

测试文件:test.cpp

#include "Check.h"
#include <windows.h>
#include <stdio.h>

#pragma comment(lib, "Ws2_32.lib")

DWORD __stdcall ProSend(void* param);
DWORD __stdcall ProRecv(void* param);


//char ip[3][2] = {1, 2, 3, 4, 5, 6};   //3line 2row
char* szIP = "220.181.6.18";

char ip[3][16] = {0};
void ImitateIP()
{
strcpy((char*)&ip[0], "220.181.6.18");
strcpy((char*)&ip[1], "61.135.253.12");
strcpy((char*)&ip[2], "127.0.0.1");
}

void main()
{
int i = 0;
ImitateIP();
printf("%s/n%s/n%s/n", ip[0], ip[1], ip[2]);
/*
uint ul = 1;
::ioctlsocket(sRaw, FIONBIO, (uint*)&ul);
*/
kyPing Ping;
if(!Ping.Init())
{
   printf("ping init error()!/n");
   return;
}

DWORD thrdID;
if(NULL == CreateThread(NULL, 0, (LPTHREAD_START_ROUTINE)ProSend, &Ping, 0, &thrdID))
{
   printf("create send thread failed!/n");
}

if(NULL == CreateThread(NULL, 0, (LPTHREAD_START_ROUTINE)ProRecv, &Ping, 0, &thrdID))
{
   printf("create recv thread failed!/n");
}

getchar();


}

DWORD __stdcall ProSend(void* param)
{
kyPing* Ping = (kyPing*)param;

int i = 0;
while(i < 3)
{
   if(Ping->PingSend((char*)&ip[i], i))
   {
    printf("send success!/n");
   }
   i++;
/*
   while(!Ping->PingRecv())
   {
    Sleep(1000);
   }
*/
}

printf("thread ProSend exit!/n");

return 0;
}

DWORD __stdcall ProRecv(void* param)
{
printf("***thread ProRecv start!/n");;

kyPing* Ping = (kyPing*)param;
while(!Ping->PingRecv())
{
   Sleep(1000);
}

while(!Ping->PingRecv())
{
   Sleep(1000);
}

printf("***thread ProRecv exit!/n");

return 0;
}

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值