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

📄 socket.cpp

📁 一个VC++的MFC PING程序(附带运行文件可删)
💻 CPP
字号:
#include "stdafx.h"
//预编译头文件通过编译stdafx.cpp生成,以工程名命名,
//由于预编译的头文件的后缀是“.pch”,所以编译结果文件是ping.pch。

//编译器通过一个头文件stdafx.h来使用预编译头文件。
//stdafx.h这个头文件名是可以在project的编译设置里指定的。
//编译器认为,所有在指令#include "stdafx.h"前的代码都是预编译的,
//它跳过#include "stdafx. h"指令,使用projectname.pch编译这条指令之后的所有代码。

#include <winsock.h>

#pragma comment(lib, "wsock32.lib")//

#define ICMP_ECHO 8
#define ICMP_ECHOREPLY 0
#pragma pack(push,1)//
typedef struct iphdr {
	unsigned int h_len:4;          // length of the header
	unsigned int version:4;        // Version of IP
	unsigned char tos;             // Type of service
	unsigned short total_len;      // total length of the packet
	unsigned short ident;          // unique identifier
	unsigned short frag_and_flags; // flags
	unsigned char  ttl; 
	unsigned char proto;           // protocol (TCP, UDP etc)
	unsigned short checksum;       // IP checksum
	unsigned int sourceIP;
	unsigned int destIP;
}IpHeader;

typedef struct _ihdr {
	BYTE i_type;       /* ICMP 包类型 */
	BYTE i_code;	   /* ICMP 包子类型 */
	USHORT i_cksum;	   /* 校验和 */
	USHORT i_id;	   /* 报文ID */
	USHORT i_seq;	   /* 报文序号 */
	ULONG timestamp;   /* 发送时间 */
}IcmpHeader;
#pragma pack(pop)//

USHORT checksum(USHORT *buffer, int size);

SOCKET	m_socket;
int		seq_no = 0;

BOOL ping( const char *ipaddr, char	*resp )
{
	struct sockaddr_in	dest,from;
	int					fromlen;
	int					res;
	int					datasize = 32;
	IcmpHeader			*icmphdr;
	IpHeader			*iphdr;
	int					iphdrlen;
	char				*datapart;
	char				pkt[1024];
	
	memset(&dest,0,sizeof(dest));
	dest.sin_addr.s_addr = inet_addr(ipaddr);//将地址转换成一个整数
	dest.sin_family = AF_INET;

	datasize += sizeof(IcmpHeader);

	memset(pkt,0,1024);
	icmphdr = (IcmpHeader*)pkt;
//填充报文头
	icmphdr->i_type = ICMP_ECHO;
	icmphdr->i_code = 0;
	icmphdr->i_cksum = 0;
	icmphdr->i_seq = seq_no;
	seq_no = (seq_no + 1) % 100;
  	icmphdr->timestamp = GetTickCount();

	datapart = pkt + sizeof(IcmpHeader);
	memset(datapart,'E', datasize - sizeof(IcmpHeader));

	icmphdr->i_cksum = checksum((USHORT*)pkt,datasize);

	res = sendto(m_socket,pkt,datasize,0,(struct sockaddr*)&dest, sizeof(dest));
	if (res == SOCKET_ERROR)
	{
		if (WSAGetLastError() == WSAETIMEDOUT)
		{
			strcpy(resp,"发送超时!");
			return FALSE;
		}
		strcpy(resp,"发送失败!");
		return FALSE;
	}

	fromlen = sizeof(from);
	res = recvfrom(m_socket,pkt,1024,0,(struct sockaddr*)&from,&fromlen);
	if (res == SOCKET_ERROR)
	{
		int	err = WSAGetLastError();
		if (err == WSAETIMEDOUT)
		{
			strcpy(resp,"接收超时!");
			return FALSE;
		}
		strcpy(resp,"接收失败!");
		return FALSE;
	}

	iphdr = (IpHeader *)pkt;
	iphdrlen = iphdr->h_len * 4 ; // number of 32-bit words *4 = bytes
	icmphdr = (IcmpHeader*)(pkt + iphdrlen);

	if (icmphdr->i_type != ICMP_ECHOREPLY) {
		strcpy(resp,"未知的回应");
		return FALSE;
	}
	
	int dist = GetTickCount() - icmphdr->timestamp;
	if(dist < 0)
		dist = 0;
	sprintf(resp,"收到来自 %s: %d 字节  费时: %d ms ",
		inet_ntoa(from.sin_addr),
		res - iphdrlen - sizeof(IcmpHeader),
		dist);
	return TRUE;
}

USHORT checksum(USHORT *buffer, int size)
{
  unsigned long cksum=0;

  while(size >1) {
	cksum+=*buffer++;
	size -=sizeof(USHORT);
  }
  
  if(size ) {
	cksum += *(UCHAR*)buffer;
  }

  cksum = (cksum >> 16) + (cksum & 0xffff);
  cksum += (cksum >>16);
  return (USHORT)(~cksum);
}

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -