• vc实现ping


    //ping.h
    #ifndef _CPING_H_
    #define _CPING_H_
    #include <Winsock2.h>
    #include <Windows.h>
    #pragma pack(1)
    
    #define ICMP_ECHOREPLY	0
    #define ICMP_ECHOREQ	8
    #define REQ_DATASIZE	32		// Echo 请求数据的大小
    
    class CPing
    {
    public:
    	//ping host, nRetries-ping次数
    	bool Ping(LPCSTR pstrHost, UINT nRetries = 4);
    
    	void Result(int* nElapseTime, float* fMissPack = NULL, u_char* cTTL = NULL);
    	//void Result(CPing::REQ_RESULT& result);
    
    private:
    	int  WaitForEchoReply(SOCKET s);
    	//ICMP回应的请求和回答函数
    	int		SendEchoRequest(SOCKET, LPSOCKADDR_IN);
    	DWORD	RecvEchoReply(SOCKET, LPSOCKADDR_IN, u_char *);
    	u_short in_cksum(u_short *addr, int len);
    
    private:
    	struct REQ_RESULT
    	{
    		int			nElapseTime;	//请求响应时间。
    		u_char		cTTL;			//请求TTL(生存时间)
    		float		fMissPack;	//丢包率
    	};
    
    	REQ_RESULT m_Result;
    };
    
    // IP Header -- RFC 791
    typedef struct tagIPHDR
    {
    	u_char  VIHL;			// Version and IHL
    	u_char	TOS;			// Type Of Service
    	short	TotLen;			// Total Length
    	short	ID;				// Identification
    	short	FlagOff;		// Flags and Fragment Offset
    	u_char	TTL;			// Time To Live
    	u_char	Protocol;		// Protocol
    	u_short	Checksum;		// Checksum
    	struct	in_addr iaSrc;	// Internet Address - Source
    	struct	in_addr iaDst;	// Internet Address - Destination
    }IPHDR, *PIPHDR;
    
    
    // ICMP Header - RFC 792
    typedef struct tagICMPHDR
    {
    	u_char	Type;			// Type
    	u_char	Code;			// Code
    	u_short	Checksum;		// Checksum
    	u_short	ID;				// Identification
    	u_short	Seq;			// Sequence
    	char	Data;			// Data
    }ICMPHDR, *PICMPHDR;
    
    
    
    // ICMP Echo Request
    typedef struct tagECHOREQUEST
    {
    	ICMPHDR icmpHdr;
    	DWORD	dwTime;
    	char	cData[REQ_DATASIZE];
    }ECHOREQUEST, *PECHOREQUEST;
    
    
    // ICMP Echo Reply
    typedef struct tagECHOREPLY
    {
    	IPHDR	ipHdr;
    	ECHOREQUEST	echoRequest;
    	char    cFiller[256];
    }ECHOREPLY, *PECHOREPLY;
    
    #pragma pack()
    
    #endif
    

      

    //ping.cpp
    #include "ping.h"
    
    #pragma comment(lib, "ws2_32.lib")
    
    bool CPing::Ping(LPCSTR pstrHost, UINT nRetries)
    {
    	//创建一个Raw套节字
    	SOCKET rawSocket = socket(AF_INET, SOCK_RAW, IPPROTO_ICMP);
    	if (rawSocket == INVALID_SOCKET) 
    	{
    		int err = WSAGetLastError();
    		return false;
    	}
    	int nNetTimeout = 1000;//1秒 
    	//发送时限
    	setsockopt(rawSocket, SOL_SOCKET, SO_SNDTIMEO, (char *)&nNetTimeout,sizeof(int));
    	//接收时限
    	setsockopt(rawSocket, SOL_SOCKET, SO_RCVTIMEO, (char *)&nNetTimeout,sizeof(int));
    
    	//获得主机信息
    	LPHOSTENT lpHost = gethostbyname(pstrHost);
    	if (lpHost == NULL)
    	{
    		return false;
    	}
    	
    	//构造目标套节字地址信息
    	struct    sockaddr_in saDest;
    	struct    sockaddr_in saSrc;
    	saDest.sin_addr.s_addr = *((u_long FAR *) (lpHost->h_addr));
    	saDest.sin_family = AF_INET;
    	saDest.sin_port = 3077;//0;
    
    	DWORD	 dwTimeSent;
    	u_char   cTTL;
    	int		nRet;
    	int		nRecvNum = 0;
    	int		nTotalTime = 0;
    
    	//多次ping
    	for (UINT nLoop = 0; nLoop < nRetries; ++nLoop)
    	{
    		//发送ICMP回应请求
    		if ((nRet = SendEchoRequest(rawSocket, &saDest)) < 0)
    		{
    			break;
    		}
    
    		if ((nRet = WaitForEchoReply(rawSocket)) == SOCKET_ERROR)
    		{
    			break;
    		}
    		if (nRet)
    		{
    			//获得回应
    			if ( (dwTimeSent = RecvEchoReply(rawSocket, &saSrc, &cTTL)) < 0)
    			{
    				nRet = dwTimeSent;
    				break;
    			}
    			//计算时间
    			nTotalTime += GetTickCount() - dwTimeSent;
    			//Sleep(1000);
    			++nRecvNum;
    		}
    	}
    	closesocket(rawSocket);
    	if (nRecvNum > 0 && nRet >= 0)
    	{
    		m_Result.nElapseTime = nTotalTime/nRetries;
    		m_Result.cTTL = cTTL;
    		m_Result.fMissPack = (float)(nRetries - nRecvNum)/nRetries;
    		return true;
    	}
    
    	return false;
    }
    
    //发送ICMPECHO数据包请求
    int CPing::SendEchoRequest(SOCKET s,LPSOCKADDR_IN lpstToAddr) 
    {
    	static ECHOREQUEST echoReq;
    	static int nId = 1;
    	static int nSeq = 1;
    	int nRet;
    
    	//构造回应请求
    	echoReq.icmpHdr.Type		= ICMP_ECHOREQ;
    	echoReq.icmpHdr.Code		= 0;
    	echoReq.icmpHdr.Checksum	= 0;
    	echoReq.icmpHdr.ID			= nId++;
    	echoReq.icmpHdr.Seq			= nSeq++;
    
    	for (nRet = 0; nRet < REQ_DATASIZE; nRet++)
    		echoReq.cData[nRet] = ' '+nRet;
    
    	//保存发送时间
    	echoReq.dwTime	= GetTickCount();
    
    	echoReq.icmpHdr.Checksum = in_cksum((u_short *)&echoReq, sizeof(ECHOREQUEST));
    
    	//发送请求
    	nRet = sendto(s,						
    				 (LPSTR)&echoReq,			
    				 sizeof(ECHOREQUEST),
    				 0,							
    				 (LPSOCKADDR)lpstToAddr, 
    				 sizeof(SOCKADDR_IN));   
    	//检查返回值
    	if (nRet == SOCKET_ERROR) 
    	{
    	}
    
    	return (nRet);
    }
    
    //接收ICMPECHO数据包回应
    DWORD CPing::RecvEchoReply(SOCKET s, LPSOCKADDR_IN lpsaFrom, u_char *pTTL) 
    {
    	ECHOREPLY echoReply;
    	int nRet;
    	int nAddrLen = sizeof(struct sockaddr_in);
    
    	//接收请求回应
    	nRet = recvfrom(s,					
    					(LPSTR)&echoReply,	
    					sizeof(ECHOREPLY),	
    					0,					
    					(LPSOCKADDR)lpsaFrom,
    					&nAddrLen);			
    
    	//检查返回值
    	if (nRet == SOCKET_ERROR) 
    	{
    		return nRet;
    	}
    
    	//返回发送的时间
    	*pTTL = echoReply.ipHdr.TTL;
    
    	return(echoReply.echoRequest.dwTime);   		
    }
    
    //等待回应
    int CPing::WaitForEchoReply(SOCKET s)
    {
    	struct timeval Timeout;
    	fd_set readfds;
    
    	readfds.fd_count = 1;
    	readfds.fd_array[0] = s;
    	Timeout.tv_sec = 1;
        Timeout.tv_usec = 0;
    
    	return(select(1, &readfds, NULL, NULL, &Timeout));
    }
    
    //转换地址
    u_short CPing::in_cksum(u_short *addr, int len)
    {
    	register int nleft = len;
    	register u_short *w = addr;
    	register u_short answer;
    	register int sum = 0;
    
    	while( nleft > 1 )  {
    		sum += *w++;
    		nleft -= 2;
    	}
    
    	if( nleft == 1 ) {
    		u_short	u = 0;
    
    		*(u_char *)(&u) = *(u_char *)w ;
    		sum += u;
    	}
    
    	sum = (sum >> 16) + (sum & 0xffff);	
    	sum += (sum >> 16);			
    	answer = ~sum;				
    	return (answer);
    }
    
    void CPing::Result(int* nElapseTime, float* fMissPack, u_char* cTTL)
    {
    	if (nElapseTime)
    	{
    		*nElapseTime = m_Result.nElapseTime;
    	}
    	if (fMissPack)
    	{
    		*fMissPack = m_Result.fMissPack;
    	}
    	if (cTTL)
    	{
    		*cTTL = m_Result.cTTL;
    	}
    }
    

      

    //main.cpp
    #include <stdlib.h>
    #include <iostream>
    #include <string>
    #include "ping.h"
    
    int main(int argn, char *argv[])
    {
    	WORD wVersionRequested;
    	WSADATA wsaData;
    	int err;
    
    	wVersionRequested = MAKEWORD( 1, 1 );
    
    	err = WSAStartup( wVersionRequested, &wsaData );
    
    	CPing ping;
    	bool bResult = false;
    	if (argn == 2)
    	{
    		bResult = ping.Ping(argv[1]);
    	}
    	else
    	{
    		bResult = ping.Ping("www.baidu.com");
    	}
    	
    	std::cout << "result : " << bResult << std::endl;
    	if (bResult)
    	{
    		int nTime;
    		u_char nTTL;
    		float fMiss;
    		ping.Result(&nTime, &fMiss, &nTTL);
    
    		std::cout << "time : " << nTime << " TTL : " << (int)nTTL << " miss : " << fMiss*100 << "% " << std::endl;
    	}
    	return 0;
    }
    

      

  • 相关阅读:
    mysql数据库函数 concat 字段类型转化、字段拼接
    SSH2中的No result defined for action的问题
    导致表单重复提交(两次)的原因--css{url()}与a标签
    详解jar命令打包生成双击即可运行的Java程序
    21IO流 和缓冲流 和处理流
    20File
    19(1)hashmap,hashtable
    IntelliJ IDEA注册码激活
    19映射
    18泛型
  • 原文地址:https://www.cnblogs.com/chunxi/p/3754963.html
Copyright © 2020-2023  润新知