win32 c++ ping 测速网游登陆服务器?

yynetsdk 2012-07-26 10:02:09

// Win32Ping.h: interface for the KWin32Ping class.
//
//////////////////////////////////////////////////////////////////////

#if !defined(AFX_WIN32PING_H__C183B112_6516_4FA5_B4CB_860ED5D98728__INCLUDED_)
#define AFX_WIN32PING_H__C183B112_6516_4FA5_B4CB_860ED5D98728__INCLUDED_

#if _MSC_VER > 1000
#pragma once
#endif // _MSC_VER > 1000

#include <winsock.h>
#pragma comment(lib, "ws2_32")

#ifndef BUFSIZ
#define BUFSIZ 256
#endif

typedef int (*fnCallBackOutput)(LPVOID pVoid, unsigned int nParam, unsigned int nResult);

typedef struct {
unsigned char Ttl; // Time To Live
unsigned char Tos; // Type Of Service
unsigned char Flags; // IP header flags
unsigned char OptionsSize; // Size in bytes of options data
unsigned char *OptionsData; // Pointer to options data
} IP_OPTION_INFORMATION, * PIP_OPTION_INFORMATION;

typedef struct {
DWORD Address; // Replying address
unsigned long Status; // Reply status
unsigned long RoundTripTime; // RTT in milliseconds
unsigned short DataSize; // Echo data size
unsigned short Reserved; // Reserved for system use
void *Data; // Pointer to the echo data
IP_OPTION_INFORMATION Options; // Reply options
} IP_ECHO_REPLY, * PIP_ECHO_REPLY;

#define PINGTIMEOUT 10000
#define PINGERROR -1

class KWin32Ping
{
public:
KWin32Ping();
virtual ~KWin32Ping();

bool SetParam(const char *pszAddr, LPVOID pDlg, fnCallBackOutput pCallFun, int nIndex);
int PingAddress();
private:
// 定义函数三个指针类型
//从ICMP.DLL中得到函数入口地址
typedef HANDLE (WINAPI* pfnHV)(VOID);
typedef BOOL (WINAPI* pfnBH)(HANDLE);
typedef DWORD (WINAPI* pfnDHDPWPipPDD)(HANDLE, DWORD, LPVOID, WORD,
PIP_OPTION_INFORMATION, LPVOID, DWORD, DWORD); // evil, no?

char m_pszAddress[BUFSIZ];
LPVOID m_pVoid;
fnCallBackOutput m_pCallFun;
int m_nIndex;

//网络相关
int m_nNetStartUp;
HINSTANCE m_hIcmp;

pfnHV m_pIcmpCreateFile;
pfnBH m_pIcmpCloseHandle;
pfnDHDPWPipPDD m_pIcmpSendEcho;
};

#endif // !defined(AFX_WIN32PING_H__C183B112_6516_4FA5_B4CB_860ED5D98728__INCLUDED_)





// Win32Ping.cpp: implementation of the KWin32Ping class.
//
//////////////////////////////////////////////////////////////////////

#include "stdafx.h"
#include "win32ping.h"


#define GOTOFINISHED(nRet)\
{\
if (NULL != m_pVoid && NULL != m_pCallFun && -1 != m_nIndex)\
{\
m_pCallFun(m_pVoid, m_nIndex, nRet);\
}\
return nRet;\
}\

//////////////////////////////////////////////////////////////////////
// Construction/Destruction
//////////////////////////////////////////////////////////////////////
KWin32Ping::KWin32Ping ()
:m_pVoid(NULL),
m_pCallFun(NULL),
m_nIndex(-1),
m_nNetStartUp(-1),
m_hIcmp(NULL),
m_pIcmpCreateFile(NULL),
m_pIcmpCloseHandle(NULL),
m_pIcmpSendEcho(NULL)
{
memset(m_pszAddress, 0, sizeof(m_pszAddress));

//初始化连接
WSADATA wsaData;
m_nNetStartUp = ::WSAStartup(0x0202, &wsaData);

m_hIcmp = ::LoadLibrary("ICMP.DLL");

if (NULL != m_hIcmp)
{
m_pIcmpCreateFile = (pfnHV)::GetProcAddress(m_hIcmp, "IcmpCreateFile");
m_pIcmpCloseHandle = (pfnBH)::GetProcAddress(m_hIcmp, "IcmpCloseHandle");
m_pIcmpSendEcho = (pfnDHDPWPipPDD)::GetProcAddress(m_hIcmp, "IcmpSendEcho");
}
}

bool KWin32Ping ::SetParam(const char *pszAddr,
LPVOID pDlg,
fnCallBackOutput pCallFun,
int nIndex)
{
memset(m_pszAddress, 0, sizeof(m_pszAddress));
if (strlen(pszAddr) > sizeof(m_pszAddress) - 1)
return false;

memcpy(m_pszAddress, pszAddr, strlen(pszAddr));
m_pVoid = pDlg;
m_pCallFun = pCallFun;
m_nIndex = nIndex;

return true;
}

KWin32Ping ::~KWin32Ping()
{

if (NULL != m_hIcmp)
{
::FreeLibrary(m_hIcmp);
m_hIcmp = NULL;
}

::WSACleanup();
}

//返回ping的时间单位是ms,如果过程中出现异常那么返回PINGTIMEOUT
//直接使用windows自带的dll,其实也可以自己写程序来实现ping
int KWin32Ping ::PingAddress()
{
//地址不为空
if (NULL == m_pszAddress || m_pszAddress[0] =='\0')
GOTOFINISHED(PINGERROR);

if (0 != m_nNetStartUp)
GOTOFINISHED(PINGERROR);

if (NULL == m_hIcmp)
GOTOFINISHED(PINGERROR);

//将地址转为ip
struct hostent* phe;
if ((phe = gethostbyname(m_pszAddress)) == 0)
GOTOFINISHED(PINGERROR);


if ((NULL == m_pIcmpCreateFile) ||
(NULL == m_pIcmpCloseHandle) ||
(NULL == m_pIcmpSendEcho)
)
{
GOTOFINISHED(PINGERROR);
}

// 打开ping服务
HANDLE hIP = m_pIcmpCreateFile();
if (hIP == INVALID_HANDLE_VALUE) {
GOTOFINISHED(PINGERROR);
}

// 构造ping数据包
char acPingBuffer[64];
memset(acPingBuffer, '\xAA', sizeof(acPingBuffer));
PIP_ECHO_REPLY pIpe = (PIP_ECHO_REPLY)GlobalAlloc( GMEM_FIXED | GMEM_ZEROINIT,
sizeof(IP_ECHO_REPLY) + sizeof(acPingBuffer));
if (pIpe == 0)
{
GOTOFINISHED(PINGERROR);
}
pIpe->Data = acPingBuffer;
pIpe->DataSize = sizeof(acPingBuffer);

// 发送ping数据包
DWORD dwStatus = m_pIcmpSendEcho(hIP, *((DWORD*)phe->h_addr_list[0]),
acPingBuffer, sizeof(acPingBuffer), NULL, pIpe,
sizeof(IP_ECHO_REPLY) + sizeof(acPingBuffer), 3000);
if (dwStatus != 0)
{
/*
cout << "Addr: " <<
int(LOBYTE(LOWORD(pIpe->Address))) << "." <<
int(HIBYTE(LOWORD(pIpe->Address))) << "." <<
int(LOBYTE(HIWORD(pIpe->Address))) << "." <<
int(HIBYTE(HIWORD(pIpe->Address))) << ", " <<
"RTT: " << int(pIpe->RoundTripTime) << "ms, " <<
"TTL: " << int(pIpe->Options.Ttl) << endl;

*/
GOTOFINISHED(int(pIpe->RoundTripTime));
}
else
{
GOTOFINISHED(PINGTIMEOUT);
}

// 关闭,回收资源
GlobalFree(pIpe);

return PINGTIMEOUT;
}

...全文
364 13 打赏 收藏 转发到动态 举报
写回复
用AI写文章
13 条回复
切换为时间正序
请发表友善的回复…
发表回复
vcorange 2012-08-22
  • 打赏
  • 举报
回复
好像同步,这样意味着需要开条线程 去执行 ping

IP 的 tos fragment option 有定义,但好像没有使用
WinEggDrop 2012-08-20
  • 打赏
  • 举报
回复
游戏服务器基本是禁止ping的,私服就不清楚了,不信自己ping下魔兽世界的游戏服务器看。
bsnry 2012-07-28
  • 打赏
  • 举报
回复
lz 要开源的话,不如写博客


上传供人下载

利人利己
oyljerry 2012-07-27
  • 打赏
  • 举报
回复
分享?
Gloveing 2012-07-27
  • 打赏
  • 举报
回复
楼主是在分享么?
gmyhbio 2012-07-27
  • 打赏
  • 举报
回复
send + GetTickCount不是就行吗?
Gloveing 2012-07-27
  • 打赏
  • 举报
回复
不错
yynetsdk 2012-07-27
  • 打赏
  • 举报
回复
分享 并 探讨。
yynetsdk 2012-07-27
  • 打赏
  • 举报
回复
分享 并 探讨。
  • 打赏
  • 举报
回复
无论如何,支持下楼主
翅膀又硬了 2012-07-27
  • 打赏
  • 举报
回复
不明白楼主在干什么

18,356

社区成员

发帖
与我相关
我的任务
社区描述
VC/MFC 网络编程
c++c语言开发语言 技术论坛(原bbs)
社区管理员
  • 网络编程
加入社区
  • 近7日
  • 近30日
  • 至今
社区公告
暂无公告

试试用AI创作助手写篇文章吧