利用 Winsock 完成类似于系统自带的 ping 远程主机的功能

这篇博客介绍了如何利用Winsock库在C++中实现一个类似于系统ping命令的程序,涉及ICMP协议,域名解析,连接性测试等功能。通过编程实现发送和接收ICMP报文,对远程主机进行ping操作,同时程序能处理主机有多个IP的情况。实验结果显示,程序成功模拟了系统ping命令,包括对被封禁域名的响应。
摘要由CSDN通过智能技术生成

数据通信实验

一、 实验名称及内容

名称:利用 Winsock 完成类似于系统自带的 ping 远程主机的功能

内容:利用 Winsock 完成基于 ICMP 协议的 ping 程序,该程序完成类似于系统自带的 ping 远程主机的功能,可以直接 ping IP 地址,也可以自动进行域名解析,并且可以指定 ping 次数和统计 ping 结果,基本包含了系统自带的 ping 命令的基本功能。并且,若一台远程主机有多个 IP,则该程序会自动依次 ping 该主机所有 IP。用户可以通过该程序 ping 远程主机来测试连接性。

二、实验过程和结果

环境

物理主机系统macOS Catalina 10.15.4

虚拟机系统Windows 10 专业版 x64

计算机名691B

虚拟机软件Parallels Desktop 15 for Mac Pro Edition, version 15.1.4 (47270)

编程环境(IDE)Visual Studio 2019

程序设计

  1. 域名解析(获取远程主机名)
    1. 调用 WSAStartup() 函数,初始化 winsock
    2. 调用 getaddrinfo() 函数,获得指定 IP 或域名的主机信息,完成域名解析
  2. ping 远程主机,循环指定次数,默认 4 4 4
    1. 调用 WSAStartup() 函数,初始化 winsock
    2. 调用 socket() 函数创建一个 Socket (PF_INET, SOCK_RAW, IPPROTO_ICMP)
    3. 调用 setsockopt() 设置接收超时(1s)
    4. 设置目的地址
    5. 构造 ICMP 封包
      1. 构造 ICMP 报头
      2. 在报头后填充数据,可以任意
      3. 计算校验和
    6. 调用 sendto() 函数发送 ICMP 报文
    7. 调用 recvfrom() 函数接收 ICMP 报文
    8. 统计 ping 信息

程序流程图

在这里插入图片描述

程序使用

编译后在命令行运行可执行程序:

myping.exe [IP/DN] ([times](default 4 times))

如:

myping.exe baidu.com
myping.exe baidu.com 10
myping.exe 39.156.69.79 10

程序主体说明

数据结构
#include <stdio.h>
#include <time.h>
#include <Winsock2.h>
#include <ws2tcpip.h>
#include <Windows.h> 
#include <sstream>
#include <iostream>
#include <string>
using namespace std;

#pragma comment (lib, "ws2_32.lib")

// 2字节 对齐 sizeof(icmp_header) == 8 
// 这是ping 在wireshark抓包中的数据结构 
typedef struct icmp_header					// ICMP报头
{
   
    unsigned char icmp_type;    		// 消息类型
    unsigned char icmp_code;    		// 代码
    unsigned short icmp_checksum;   // 校验和
    unsigned short icmp_id;     		// 用来惟一标识此请求的ID号,通常设置为进程ID
    unsigned short icmp_sequence;   // 序列号
} icmp_header;
函数
u_short ss2n(string s)		// 将字符串转为数字,用来将argv指向的字符串类型的指定ping次数转为短整型
{
   
	stringstream ss;
	u_short u;
	ss << s;
	ss >> u;
	return u;
}
// 计算校验和 
unsigned short chsum(struct icmp_header* picmp, int len)
{
   
    long sum = 0;
    unsigned short* pusicmp = (unsigned short*)picmp;
    while (len > 1)
    {
   
        sum += *(pusicmp++);
        if (sum & 0x80000000)
            sum = (sum & 0xffff) + (sum >> 16);
        len -= 2;
    }
    if (len)
        sum += (unsigned short)*(unsigned 
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值