首页产品库评测行情新闻|手机数码笔记本台式机DIY硬件数字家庭数码相机办公外设|软件下载游戏开发|社区

更多

数码相机
MP4
LCD
机箱
音箱

软件资讯设计 工具 系统 开发 安全 办公 陶吧 IT教育 Vista频道 | 下载中心酷我音乐盒 腾讯QQ
天极网 > 开发频道>原始套接字透析之实现Ping

原始套接字透析之实现Ping

2006-11-13 07:00作者:宋宝华出处:天极开发责任编辑:方舟

  为了在Visual C++中更加方便地使用发送和接收ICMP报文,我们可以使用由Jay Wheeler编写的CIcmp(An ICMP Class For MFC)类,在著名的开发网站的如下地址可以下载。

  这个类的简要框架如下:

class CIcmp: public CSocket
{
 // Attributes
 public:
  BOOL OpenNewSocket(HWND hWnd, unsigned int NotificationMessage, long NotifyEvents);
  BOOL OpenNewSocket(HWND hWnd, unsigned int NotificationMessage, long NotifyEvents, int AFamily, int AType, int AProtocol);
  int CloseIcmpSocket(void);
  BOOL Connect(int ReceiveTimeout, int SendTimeout);
  BOOL Connect(LPINT ReceiveTimeout, LPINT SendTimeout, int AFamily, int AType, int AProtocol);
  int SetTTL(int TTL);
  int SetAsynchNotification(HWND hWnd, unsigned int Message, long Events);
  int Receive(LPSTR pIcmpBuffer, int IcmpBufferSize);
  unsigned long GetIPAddress(LPSTR iHostName);
  int Ping(LPSTR pIcmpBuffer, int IcmpBufferSize);
  unsigned short IcmpChecksum(unsigned short FAR *lpBuf, int Len);
  void DisplayError(CString ErrorType, CString FunctionName);
  // Operations
 public:
  CIcmp(void);
  CIcmp(CIcmp &copy);
  ~CIcmp(void);
 public:
  // I/O Buffer Pointers
  LPIcmpHeader pIcmpHeader;
  LPIpHeader pIpHeader;

  SOCKET icmpSocket;
  SOCKADDR_IN icmpSockAddr;
  SOCKADDR_IN rcvSockAddr;
  DWORD icmpRoundTripTime;
  DWORD icmpPingSentAt;
  DWORD icmpPingReceivedAt;

  int icmpRcvLen;
  int icmpHops;
  int icmpMaxHops;
  int icmpCurSeq;
  int icmpCurId;
  int icmpPingTimer;
  int icmpSocketError;
  int icmpSocketErrorMod;
  unsigned long icmpHostAddress;
 protected:
};

  初始化网络连接的函数:

BOOL CIcmp::Connect(LPINT ReceiveTimeout, LPINT SendTimeout, int AFamily, int AType, int AProtocol)
{
 int Result;
 icmpSocket = NULL;
 icmpSocket = socket(AFamily, AType, AProtocol);

 if (icmpSocket == INVALID_SOCKET)
 {
  icmpSocketError = WSAGetLastError();
  icmpSocketErrorMod = 1;
  return FALSE;
 }

 //
 // Set receive timeout
 //

 Result = setsockopt(icmpSocket, SOL_SOCKET, SO_RCVTIMEO, (char*)ReceiveTimeout, sizeof(int));
 if (Result == SOCKET_ERROR)
 {
  icmpSocketError = WSAGetLastError();
  icmpSocketErrorMod = 2;
  closesocket(icmpSocket);
  icmpSocket = INVALID_SOCKET;
  return FALSE;
 }

 //
 // Set send timeout
 //
 Result = setsockopt(icmpSocket, SOL_SOCKET, SO_SNDTIMEO, (char*)SendTimeout,sizeof(int));
 if (Result == SOCKET_ERROR)
 {
  icmpSocketError = WSAGetLastError();
  icmpSocketErrorMod = 3;
  closesocket(icmpSocket);
  icmpSocket = INVALID_SOCKET;
  return FALSE;
 }
 icmpCurSeq = 0;
 icmpCurId = (USHORT)GetCurrentProcessId();
 icmpHops = 0;

 return TRUE;
}

  接收的函数:

int CIcmp::Receive(LPSTR pIcmpBuffer, int IcmpBufferSize)
{
LPSOCKADDR pRcvSockAddr = (LPSOCKADDR)&rcvSockAddr;

int Result;
int RcvIpHdrLen;

icmpPingReceivedAt = GetTickCount();

icmpCurId = 0;

rcvSockAddr.sin_family = AF_INET;
rcvSockAddr.sin_addr.s_addr = INADDR_ANY;
rcvSockAddr.sin_port = 0;

RcvIpHdrLen = sizeof rcvSockAddr;

Result = recvfrom (icmpSocket,
pIcmpBuffer,
IcmpBufferSize,
0,
pRcvSockAddr,
&RcvIpHdrLen);

if (Result == SOCKET_ERROR)
{
icmpSocketError = WSAGetLastError();
icmpSocketErrorMod = 1;
DisplayError ("Receive","CIcmp::Receive");
return Result;
}

icmpRcvLen = Result;

pIpHeader = (LPIpHeader)pIcmpBuffer;

RcvIpHdrLen = pIpHeader->HeaderLength * 4;
if (Result < RcvIpHdrLen + ICMP_MIN)
{
//
// Too few bytes received
//
MessageBox(NULL,
"Short message!",
"CIcmp::Receive",
MB_OK|MB_SYSTEMMODAL);
icmpSocketErrorMod = 2;
return Result;
}

pIcmpHeader = (LPIcmpHeader)(pIcmpBuffer + RcvIpHdrLen);

icmpCurId = pIcmpHeader->IcmpId;
icmpRoundTripTime = icmpPingReceivedAt - pIcmpHeader->IcmpTimestamp;

if (pIcmpHeader->IcmpType != ICMP_ECHOREPLY)
{
//
// Not an echo response!
//
return Result;
}

icmpCurSeq = pIcmpHeader->IcmpSeq;

return Result;
}

  异步通知主窗口:

int CIcmp::SetAsynchNotification(HWND hWnd, unsigned int Message, long Events)
{
 int Result = WSAAsyncSelect (icmpSocket,hWnd, Message, Events);
 if (Result == SOCKET_ERROR)
 {
  icmpSocketError = WSAGetLastError();
  icmpSocketErrorMod = 1;
  icmpSocket = INVALID_SOCKET;
 }
 return Result;
}

  设置TTL:

int CIcmp::SetTTL(int TTL)
{
 int Result;
 Result = setsockopt (icmpSocket, IPPROTO_IP, IP_TTL, (LPSTR)&TTL, sizeof(int));

 if (Result == SOCKET_ERROR)
 {
  icmpSocketErrorMod = 1;
  icmpSocketError = WSAGetLastError();
 }
 return Result;
}

  Ping命令的函数:

int CIcmp::Ping (LPSTR pIcmpBuffer, int DataLen)
{
 int Result;
 int IcmpBufferSize = DataLen + IcmpHeaderLength;
 pIcmpHeader = (LPIcmpHeader)pIcmpBuffer;

 memset (pIcmpBuffer, 'E', IcmpBufferSize);
 memset (pIcmpHeader, 0, IcmpHeaderLength);

 pIcmpHeader->IcmpType = ICMP_ECHO;
 pIcmpHeader->IcmpCode = 0;
 pIcmpHeader->IcmpChecksum = 0;
 pIcmpHeader->IcmpId = icmpCurId;
 pIcmpHeader->IcmpSeq = icmpCurSeq;
 pIcmpHeader->IcmpTimestamp = GetCurrentTime();

 pIcmpHeader->IcmpChecksum = IcmpChecksum ((USHORT FAR *)pIcmpBuffer,IcmpBufferSize);

 icmpPingSentAt = GetCurrentTime();
 Result = sendto (icmpSocket, pIcmpBuffer, IcmpBufferSize, 0, (LPSOCKADDR)&icmpSockAddr, sizeof icmpSockAddr);

 if (Result == SOCKET_ERROR)
 {
  icmpSocketError = WSAGetLastError();
  icmpSocketErrorMod = 1;
 }
 return Result;
}

关注此文的读者还看过:

返回开发频道首页

共3页。 上一页123

软件频道最新更新

热点推荐

IT嘉年华

编辑推荐

软件下载

热门
推荐

网友关注

软件
资料
游戏

装机推荐

文章排行

本周
本月
最新更新
天极服务|关于我们|About us|网站律师|RSS订阅|友情合作|加入我们|天极动态|网站地图|意见反馈|MSN/QQ上看天极
Copyright (C) 1999-2012 Yesky.com, All Rights Reserved 版权所有 天极网络