📄 icmp.cpp
字号:
// //
// The Icmp variable icmpPingSentAt is set to the time value at the //
// time the ping message is sent. //
// //
// Sets icmpSocketError and icmpSocketErrorMod to indicate the type //
// of error, and returns the integer result of the operation. //
// //
// icmpSocketError and icmpSocketErrorMod are preserved until the next //
// operation on this Icmp object is performed. //
// //
//////////////////////////////////////////////////////////////////////////////////
//实现PING功能,通过发送ICMP消息
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();
//发送PING的信息包
Result = sendto (icmpSocket,
pIcmpBuffer,
IcmpBufferSize,
0,
(LPSOCKADDR)&icmpSockAddr,
sizeof icmpSockAddr);
//获得数据
if (Result == SOCKET_ERROR)
{
icmpSocketError = WSAGetLastError();
icmpSocketErrorMod = 1;
}
return Result;
}
//////////////////////////////////////////////////////////////////////////////////
// //
// IcmpChecksum //
// Computes the icmp checksum of the Len data in the buffer referenced //
// by lpBuf. //
// //
// Returns an unsigned integer value of the computed checksum. //
// //
//////////////////////////////////////////////////////////////////////////////////
//计算出检查和
unsigned short CIcmp::IcmpChecksum(unsigned short FAR *lpBuf, int Len)
{
register long ChkSum = 0L;
while (Len > 1)
{
ChkSum += *(lpBuf++);
Len -= sizeof (USHORT);
}
if (Len)
ChkSum += *(UCHAR *)lpBuf;
ChkSum = (ChkSum & 0xffff) + (ChkSum>>16);
ChkSum += (ChkSum >> 16);
//
// A warning C4244 return conversion message is expected,
// so shut it off for the next line of code ONLY!
//
#pragma warning(disable : 4244)
return (~ChkSum);
#pragma warning(default : 4244)
}
//////////////////////////////////////////////////////////////////////////////////
// //
// GetIPAddress //
// Returns the value of the IP address of the host pointed by //
// iHostName as an unsigned long in network byte order, as described //
// in inet_aton //
// //
// Sets iHostName to the value of the host name returned in //
// icmpHostEnt. //
// //
// Requires the message number to send to the window, and the events //
// to notify on. //
// //
// Sets Icmp variable icmpSockAddr fields appropriately, leaving the //
// IP address in icmpSockAddr.sin_addr, and the type of address in //
// icmpSockAddr.sin_family. Also sets icmpHostEnt fields appropriately//
// //
// Sets icmpSocketError and icmpSocketErrorMod to indicate the type //
// of error, and returns the integer result of the operation. //
// //
// icmpSocketError and icmpSocketErrorMod are preserved until the next //
// operation on this Icmp object is performed. //
// //
//////////////////////////////////////////////////////////////////////////////////
//获得IP地址,需要先给定主机名
unsigned long CIcmp::GetIPAddress (LPSTR iHostName)
{
LPHOSTENT pIcmpHostEnt;
unsigned long iHostAddress;
memset (&icmpSockAddr, 0, sizeof(sockaddr_in));
pIcmpHostEnt = gethostbyname(iHostName);
if (pIcmpHostEnt == NULL)
{
icmpSocketError = WSAGetLastError();
icmpSocketErrorMod = 1;
iHostAddress = inet_addr(iHostName);
}
if ((!pIcmpHostEnt) && (iHostAddress == INADDR_NONE))
return iHostAddress;
if (pIcmpHostEnt != NULL)
memcpy (&(icmpSockAddr.sin_addr),
pIcmpHostEnt->h_addr,
pIcmpHostEnt->h_length);
else
icmpSockAddr.sin_addr.s_addr = iHostAddress;
if (pIcmpHostEnt)
icmpSockAddr.sin_family = pIcmpHostEnt->h_addrtype;
else
icmpSockAddr.sin_family = AF_INET;
iHostName = pIcmpHostEnt->h_name;
return icmpSockAddr.sin_addr.s_addr;
}
//////////////////////////////////////////////////////////////////////////////////
// //
// Receive //
// //
// Reads the socket associated with the Icmp object and returns the //
// number of bytes read, or SOCKET_ERROR, if an error occurs. //
// //
// Requires the address of the buffer to store the incoming message //
// and an integer buffer size. The buffer must be large enough to //
// contain the incoming message. In the case of an ICMP ping echo //
// response, the size would be the size of the outgoing message plus //
// the size of an ICMP header plus the size of an IP header. //
// //
// Sets icmpPingReceivedAt to the time the receive command is issued, //
// icmpRoundTripTime to the difference between icmpPingSentAt and //
// icmpPingReceivedAt, icmpCurSeq to the incoming sequence number //
// and icmpCurId to the incoming id field. //
// //
// Sets rcvSockAddr fields appropriately. //
// //
// Sets icmpSocketError and icmpSocketErrorMod to indicate the type //
// of error, and returns the integer result of the operation. //
// //
// icmpSocketError and icmpSocketErrorMod are preserved until the next //
// operation on this Icmp object is performed. //
// //
//////////////////////////////////////////////////////////////////////////////////
//数据接收,该函数返回接收到得数据得大小或者返回错误信息
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)
{
//
// 收到的字节太少
//
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)
{
//
// 不是回显响应
//
return Result;
}
icmpCurSeq = pIcmpHeader->IcmpSeq;
return Result;
}
//////////////////////////////////////////////////////////////////////////////////
// //
// DisplayError //
// Displays the provided ErrorType message prior to the decoded error //
// message in icmpSocketError and icmpSocketErrorMod. //
// //
// Sets the message box title to FunctionName. //
// //
// The message is displayed in a modal box, requiring an OK response //
// before the thread containing this method can progress. //
// //
//////////////////////////////////////////////////////////////////////////////////
void CIcmp::DisplayError(CString ErrorType, CString FunctionName)
{
CString ErrorMessage;
CString OutputMessage;
if (ErrorMessage.LoadString(icmpSocketError) == 0)
{
OutputMessage.Format("%s Error: %u-%u",
ErrorType,
icmpSocketError,
icmpSocketErrorMod);
}
else
{
OutputMessage.Format("%s Error (%u-%u) : %s",
ErrorType,
icmpSocketError,
icmpSocketErrorMod,
ErrorMessage);
}
MessageBox (NULL,OutputMessage, FunctionName, MB_OK|MB_SYSTEMMODAL);
}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -