⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 icmp.cpp

📁 Visual+C++网络通信协议分析
💻 CPP
📖 第 1 页 / 共 3 页
字号:
//																				//
//			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 + -