当前位置:网站首页>Principle and implementation of Ping

Principle and implementation of Ping

2022-07-23 05:33:00 CAir2

Ping The basic principle of depends on ICMP agreement .ICMP Baotou is as follows :
 Insert picture description here
The type and code The definition is as follows :
 Insert picture description here
 Insert picture description here

design idea

  1. Definition IP Head structure
  2. Definition ICMP Head structure
  3. structure ICPM Message and calculate ICMP Checksum
  4. adopt sendto and recvfrom Send and receive ICMP message

The code is as follows

Define the communication packet header NetStruct.h

// Network byte order , Big end 
//unsigned char header_len : 4;
// Why not define a bit pattern , Because byte order processing is required 
#pragma pack(push,1)
typedef struct IPHeader
{
    
private:
	unsigned char version_headerlen;// edition (4) ipv4-4 ipv6-6  The length of the first (4) 32(4 byte ) Bit is a cell in calculation  max=60(15*4) byte 
public:
	unsigned char tos;// Service type 
	unsigned short total_len;// Unit byte ,IP Head + Data section 
	unsigned short flag;// identification 
private:
	unsigned short flag_sep_offset;// identification 3: The offset 13
public:
	unsigned char ttl;
	unsigned char proto_type;//1-icmp 2-igmp 6-tcp 17-udp
	unsigned short check_sum;// Head checksums 
	unsigned int src_ip;
	unsigned int dest_ip;

	unsigned char version()
	{
    
		return (version_headerlen >>2) & 0x0f;
	}

	unsigned char header_len()
	{
    
		return version_headerlen & 0x0f;
	}

}IPHeader, *PIPHeader;


typedef struct ICMPHeader
{
    
	unsigned char type;
	unsigned char code;
	unsigned short check_sum;
	unsigned short flag;
	unsigned short seq;
	unsigned char data[0];// Data section 
}ICMPHeader, *PICMPHeader;

#pragma pack(pop)

structure ICMP Message and calculate the checksum Ping.cpp

unsigned short CalcCheckSum(unsigned short *pdata,int nSize)
{
    
	unsigned long check_sum = 0;
	while (nSize > 1)
	{
    
		check_sum += *pdata++;
		nSize -= sizeof(unsigned short);
	}

	if (nSize)
	{
    
		check_sum += *(unsigned short *)pdata;
	}

	check_sum = (check_sum >> 16) + (check_sum & 0xffff);
	check_sum += (check_sum >> 16);

	unsigned short result =  (unsigned short)(~check_sum);

	return result;
}

PICMPHeader NewIcmpPack(const void *icmpData, int &len)
{
    
	unsigned int pack_len = sizeof(ICMPHeader) + len;
	char *pack_buffer = new char[pack_len];
	memset(pack_buffer, 0, pack_len);

	PICMPHeader pHeader = (PICMPHeader)pack_buffer;
	memcpy(pHeader->data, icmpData, len);
	pHeader->type = 8;
	pHeader->code = 0;
	pHeader->flag = 0x1234;
	pHeader->seq = 0;
	pHeader->check_sum = CalcCheckSum((unsigned short *)pack_buffer, pack_len);
	len = pack_len;
	return pHeader;
}

void DeleteIcmpPack(PICMPHeader p)
{
    
	if(p != NULL)
	{
    
		delete [](char *)p;
	}
}

// analysis icmp Data packets 
PICMPHeader parseIcmpReply(char *pdata, unsigned int date_len)
{
    
	PIPHeader pIpHeader = (PIPHeader)pdata;
	unsigned short iHeaderLen = pIpHeader->header_len() * 4;
	//icmp  Incomplete data 
	if (date_len < iHeaderLen + sizeof(ICMPHeader))
	{
    
		cout << "ICMP pack data error" <<  endl;
		return NULL;
	}
	PICMPHeader pIcmpHeader = (PICMPHeader)pIpHeader->data;
	return pIcmpHeader;
}

Send and receive ICMP message

bool ping(const char *szIp, unsigned int timeout)
{
    
	SOCKET sock = socket(AF_INET, SOCK_RAW, IPPROTO_ICMP);
	if (sock == INVALID_SOCKET)
	{
    
		cout << "socket create failed:" << WSAGetLastError() << endl;
		return false;
	}

	// If it is linux be timeout by struct timeval
	setsockopt(sock, SOL_SOCKET, SO_RCVTIMEO, (char *)&timeout, sizeof(timeout));
	setsockopt(sock, SOL_SOCKET, SO_SNDTIMEO, (char *)&timeout, sizeof(timeout));

	sockaddr_in sock_dst = {
    0};
	sock_dst.sin_family = AF_INET;
	sock_dst.sin_addr.S_un.S_addr = inet_addr(szIp);

	int data_len = 6;
	PICMPHeader pIcmpPack = NewIcmpPack("Hellow", data_len);
	if (SOCKET_ERROR == sendto(sock, (const char *)pIcmpPack, data_len, 0, (sockaddr*)&sock_dst, sizeof(sock_dst)))
	{
    
		cout << "sendto data failed:" << WSAGetLastError() << endl;
		closesocket(sock);
		DeleteIcmpPack(pIcmpPack );
		return false;
	}
	DeleteIcmpPack(pIcmpPack );
	
	while (true)
	{
    
		char recv_buf[1024] = "";
		int ret = recvfrom(sock, recv_buf, 1024, 0, NULL, NULL);
		if (ret == SOCKET_ERROR)
		{
    
			cout << "WSAStartup failed:" << WSAGetLastError() << endl;
		}
		else
		{
    
			PICMPHeader pIcmpReplay = parseIcmpReply(recv_buf, ret);
			
			// Deal with according to the agreement icmp The reply 
		}

		break;
	}
	closesocket(sock);
	return true;
}

The test program , adopt winshark Grab the bag and see the result

ping("192.168.34.187", 3000);

 Insert picture description here

原网站

版权声明
本文为[CAir2]所创,转载请带上原文链接,感谢
https://yzsam.com/2022/204/202207221753517436.html