vc++Ping命令模拟_C/C++_编程开发_程序员俱乐部

中国优秀的程序员网站程序员频道CXYCLUB技术地图
热搜:
更多>>
 
您所在的位置: 程序员俱乐部 > 编程开发 > C/C++ > vc++Ping命令模拟

vc++Ping命令模拟

 2011/8/29 9:58:09  sxjkk  http://sxjkk.iteye.com  我要评论(0)
  • 摘要:今天思考如何用程序实现IP的探测,网上查了一些资料,要了解ICMP协议ICMP是ICMP是(InternetControlMessageProtocol)Internet控制报文协议。它是TCP/IP协议族的一个子协议。ICMP协议主要用来控制消息是指网络通不通、主机是否可达、路由是否可用等网络本身的消息参考了《Visualc++网络程序设计实例详解》的代码后,在作者的基础上稍微修改了下以便在VC2005正常运行下面是例子代码//目的IP地址
  • 标签:VC++ c++ 命令
今天思考如何用程序实现IP的探测,网上查了一些资料,要了解ICMP协议
ICMP是ICMP是(Internet Control Message Protocol)Internet控制报文协议。它是TCP/IP协议族的一个子协议。ICMP协议主要用来控制消息是指网络通不通、主机是否可达、路由是否可用等网络本身的消息

参考了《Visual c++网络程序设计实例详解》的代码后,在作者的基础上稍微修改了下以便在VC2005正常运行

下面是例子代码
// 目的IP地址,即要Ping的IP地址  
		char szDestIp[] = "169.254.41.36";  // 127.0.0.1  

		// 创建原始套节字  
		WSADATA wsaData;
		WSAStartup(MAKEWORD(2, 2), &wsaData);
		SOCKET sRaw = socket(AF_INET, SOCK_RAW, IPPROTO_ICMP);  

		// 设置接收超时  
		SetTimeout(sRaw, 3000, TRUE);  

		// 设置目的地址  
		SOCKADDR_IN dest;  
		dest.sin_family = AF_INET;  
		dest.sin_port = htons(0);  
		dest.sin_addr.S_un.S_addr = inet_addr(szDestIp);  

		// 创建ICMP封包  
		char buff[sizeof(ICMP_HDR) + 32];  
		ICMP_HDR* pIcmp = (ICMP_HDR*)buff;  

		// 填写ICMP封包数据,请求一个ICMP回显  
		pIcmp->icmp_type = 8;      
		pIcmp->icmp_code = 0;  
		pIcmp->icmp_id = (USHORT)GetCurrentProcessId();  
		pIcmp->icmp_checksum = 0;  
		pIcmp->icmp_sequence = 0;  

		// 填充数据部分,可以为任意  
		memset(&buff[sizeof(ICMP_HDR)], 'E', 32);  

		// 开始发送和接收ICMP封包  
		USHORT  nSeq = 0;  
		char recvBuf[1024];  
		SOCKADDR_IN from;  
		int nLen = sizeof(from);  
		while(TRUE)  
		{  
			static int nCount = 0;  
			int nRet;  

			// ping次数  
			if(nCount++ == 1000)  
				break;  

			pIcmp->icmp_checksum = 0;  
			pIcmp->icmp_timestamp = GetTickCount();  
			pIcmp->icmp_sequence = nSeq++;  
			pIcmp->icmp_checksum = checksum((USHORT*)buff, sizeof(ICMP_HDR) + 32);  
			nRet = sendto(sRaw, buff, sizeof(ICMP_HDR) + 32, 0, (SOCKADDR *)&dest, sizeof(dest));  
			if(nRet == SOCKET_ERROR)  
			{  
				printf(" sendto() failed: %d \n", ::WSAGetLastError());  
				return -1;  
			}
			nRet = recvfrom(sRaw, recvBuf, 1024, 0, (sockaddr*)&from, &nLen);
			if(nRet == SOCKET_ERROR)
			{  
				if(WSAGetLastError() == WSAETIMEDOUT)  
				{  
					printf(" timed out\n");  
					continue;  
				}
				printf("recvfrom() failed: %d\n", WSAGetLastError());  
				return -1;
			}  

			// 下面开始解析接收到的ICMP封包  
			int nTick = ::GetTickCount();  
			if(nRet < sizeof(IPHeader) + sizeof(ICMP_HDR))  
			{  
				printf(" Too few bytes from %s \n", inet_ntoa(from.sin_addr));  
			}  

			// 接收到的数据中包含IP头,IP头大小为20个字节,所以加20得到ICMP头  
			// (ICMP_HDR*)(recvBuf + sizeof(IPHeader));  
			ICMP_HDR* pRecvIcmp = (ICMP_HDR*)(recvBuf + 20);   
			if(pRecvIcmp->icmp_type != 0)    // 回显  
			{  
				printf(" nonecho type %d recvd \n", pRecvIcmp->icmp_type);  
				return -1;  
			}

			if(pRecvIcmp->icmp_id != GetCurrentProcessId())  
			{  
				printf(" someone else's packet! \n");  
				return -1;  
			}  

			printf("从 %s 返回 %d 字节:", inet_ntoa(from.sin_addr),nRet);  
			printf(" 数据包序列号 = %d. \t", pRecvIcmp->icmp_sequence);  
			printf(" 延时大小: %d ms", nTick - pRecvIcmp->icmp_timestamp);  
			printf(" \n");  

			// 每一秒发送一次就行了  
			Sleep(1000);
		}

		WSACleanup();
		closesocket(sRaw);


发表评论
用户名: 匿名