书上的代码,根据自己的理解对书上代码进行了一部分的更改,并尝试在一些地方使用C++改写。改进程序实现能同时对多个域名进行解析
《Windows网络编程(第2版)》
#define _WINSOCK_DEPRECATED_NO_WARNINGS
#include <winsock2.h>
#pragma comment(lib, "Ws2_32.lib")
#include<iostream>
#include<sstream>
using namespace std;
#define ICMP_MIN 8 // ICMP包的最小长度为8个字节,只包含包头
#define DEF_PACKET_SIZE 32 // 执行ping操作时指定发送数据包的缺省大小
#define MAX_PACKET 1024 // 执行ping操作时指定发送数据包的最大大小
#define ICMP_ECHO 8 // 表示ICMP包为回射请求包
#define ICMP_ECHOREPLY 0 // 表示ICMP包为回射应答包
// IP数据包头结构
typedef struct iphdr {
unsigned int h_len : 4; // 包头长度
unsigned int version : 4; // IP协议版本
unsigned char tos; // 服务类型(TOS)
unsigned short total_len; // 包的总长度
unsigned short ident; // 包的唯一标识
unsigned short frag_and_flags; // 标识
unsigned char ttl; // 生存时间(TTL)
unsigned char proto; // 传输协议 (TCP, UDP等)
unsigned short checksum; // IP校验和
unsigned int sourceIP;
unsigned int destIP;
}IpHeader;
//ICMP数据包结构
typedef struct _ihdr {
BYTE i_type; // 类型
BYTE i_code; // 编码
USHORT i_cksum; // 检验和
USHORT i_id; // 编号
USHORT i_seq; // 序列号
ULONG timestamp; // 时间戳
}IcmpHeader;
// 计算ICMP包的校验和
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);
}
// 对返回的IP数据包进行解码,定位到ICMP数据
// 因为ICMP数据包含在IP数据包中
int decode_resp(char* buf, int bytes, struct sockaddr_in* from, DWORD tid)
{
IpHeader* iphdr; // IP数据包头
IcmpHeader* icmphdr; // ICMP包头
unsigned short iphdrlen; // IP数据包头的长度
iphdr = (IpHeader*)buf; // 从buf中IP数据包头的指针,接收的数据
// 计算IP数据包头的长度
iphdrlen = iphdr->h_len * 4; // number of 32-bit words *4 = bytes
// 如果指定的缓冲区长度小于IP包头加上最小的ICMP包长度,则说明它包含的ICMP数据不完整,或者不包含ICMP数据
if (bytes < iphdrlen + ICMP_MIN) {
return -1;
}
// 定位到ICMP包头的起始位置
icmphdr =