上一篇
就在2025年8月,IETF正式发布ICMPv6新规范,新增对路径MTU发现(PMTUD)的支持!这意味着未来网络诊断将更精准地处理大包传输问题,Linux内核6.3版本已集成智能ICMP限速机制,有效防御DDoS攻击——这正是我们编写自定义Ping程序的最佳时机!
Ping命令堪称网络世界的"心电图",通过ICMP回显请求/应答机制工作:
💡小知识:Windows默认发送32字节数据包,而Linux发送56字节,这源于系统对网络栈的差异化优化。
#include <winsock2.h> #include <ws2tcpip.h> // 初始化WinSock WSADATA wsa; if (WSAStartup(MAKEWORD(2,2), &wsa) != 0) { printf("WinSock初始化失败!错误码:%d", WSAGetLastError()); exit(1); } // 创建原始套接字 SOCKET sock = socket(AF_INET, SOCK_RAW, IPPROTO_ICMP);
struct icmp_header { u_char type; // 8=Echo请求,0=Echo应答 u_char code; // 代码字段 u_short checksum; // 校验和 u_short id; // 进程ID u_short seq; // 序列号 }; // 填充ICMP头 struct icmp_header *icmp = (struct icmp_header *)packet; icmp->type = 8; // ICMP_ECHO icmp->code = 0; icmp->id = htons(getpid()); icmp->seq = htons(seq_num++); icmp->checksum = 0; icmp->checksum = checksum((u_short *)icmp, sizeof(*icmp));
struct timeval timeout = {1, 0}; // 1秒超时 setsockopt(sock, SOL_SOCKET, SO_RCVTIMEO, (char*)&timeout, sizeof(timeout)); // 统计信息 int sent = 0, received = 0, lost = 0; float min_rtt = INFINITY, max_rtt = 0, avg_rtt = 0;
while (1) { gettimeofday(&start, NULL); sendto(sock, packet, sizeof(*icmp), 0, (struct sockaddr*)&dest, sizeof(dest)); if (recvfrom(sock, buffer, sizeof(buffer), 0, NULL, NULL) > 0) { gettimeofday(&end, NULL); calculate_rtt(start, end); received++; } else { printf("请求超时!\n"); lost++; } if (++sent >= 4) break; // 发送4个包后退出 Sleep(1000); // Windows平台需用Sleep,Linux用sleep(1) }
特性 | Windows | Linux |
---|---|---|
权限要求 | 无需管理员 | 需要root权限 |
数据包大小 | 最大65500字节 | 最大65507字节 |
TTL默认值 | 128(IPv4)/64(IPv6) | 64(IPv4)/255(IPv6) |
参数控制 | ping -n 4 192.168.1.1 |
ping -c 4 192.168.1.1 |
禁止分片检测(Linux需root):
setsockopt(sock, IPPROTO_IP, IP_MTU_DISCOVER, IP_PMTUDISC_DO, sizeof(int));
路径MTU发现:
通过IP_RECVERR
选项捕获"需要分片但DF置位"的ICMP报文
时间戳扩展: 在ICMP数据区添加时间戳字段,实现微秒级精度
netsh advfirewall firewall add rule name="ICMP_Test" dir=out action=allow protocol=ICMPv4
# Linux临时关闭防火墙 iptables -I INPUT -p icmp --icmp-type echo-request -j ACCEPT
// 完整代码见GitHub仓库:https://github.com/yourname/ping-demo // 关键函数:checksum计算 unsigned short checksum(void *b, int len) { unsigned short *buf = b; unsigned int sum = 0; unsigned short result; for (sum = 0; len > 1; len -= 2) sum += *buf++; if (len == 1) sum += *(unsigned char *)buf; sum = (sum >> 16) + (sum & 0xFFFF); sum += (sum >> 16); result = ~sum; return result; }
AF_INET6
地址族处理通过本文,你不仅掌握了ICMP协议的核心机制,更获得了跨平台开发网络诊断工具的完整能力,现在就动手编译你的专属Ping程序,让网络状态一目了然!🚀
本文由 业务大全 于2025-08-23发表在【云服务器提供商】,文中图片由(业务大全)上传,本平台仅提供信息存储服务;作者观点、意见不代表本站立场,如有侵权,请联系我们删除;若有图片侵权,请您准备原始证明材料和公证书后联系我方删除!
本文链接:https://xdh.7tqx.com/wenda/702248.html
发表评论