「Ping」WinSock实作Ping

利用 Winsock 完成类似于系统自带的 ping 远程主机的功能 数据通信实验 文章目录数据通信实验一、 实验名称及内容二、实验过程和结果环境程序设计程序流程图程序使用程序主体说明数据结构函数实验结果 一、 实验名称及内容 __名称:__利用 Winsock 完成类似于系统自带的 ping 远程主机的功能 __内容:__利用 Winsock 完成基于 ICMP 协议的 ping 程序,该程序完成类似于系统自带的 ping 远程主机的功能,可以直接 ping IP 地址,也可以自动进行域名解析,并且可以指定 ping 次数和统计 ping 结果,基本包含了系统自带的 pin 阅读详情

// IP头 结构

typedef struct _iphdr

{

    unsigned int   h_len:4;        // IP首部长度

    unsigned int   version:4;      // IP协议版本

    unsigned char  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;       // 源IP地址

    unsigned int   destIP;         // 目的IP地址

} IpHeader;

 

// ICMP头 结构

typedef struct _icmphdr

{

    BYTE   i_type;                 // ICMP 报文类型

    BYTE   i_code;                 // ICMP 代码

    USHORT i_cksum;                // 检验和

    USHORT i_id;                   // 标识符

    USHORT i_seq;                  // 序列号

    // 预留空间

    ULONG  timestamp;              // 时间戳

} IcmpHeader;

 

//    构造ICMP回应请求报头

void  FillICMPData(char *icmp_data, int datasize)

{

    IcmpHeader *icmp_hdr = NULL;

    char       *datapart = NULL;

 

    icmp_hdr = (IcmpHeader*)icmp_data;

    icmp_hdr->i_type = 8;        // 请求一个ICMP回应

    icmp_hdr->i_code = 0;        // 代码字段 0

    icmp_hdr->i_id = (USHORT)GetCurrentProcessId();  // 获取当前进程一个唯一的标识符,填充为ICMP标识符

    icmp_hdr->i_cksum = 0;       // 检验和置零

    icmp_hdr->i_seq = 0;         // 序列号

    // icmp_data 加上头部大小,datapart就指向ICMP数据包中的具体内容

    datapart = icmp_data + sizeof(IcmpHeader); 

    // 在数据包正文中填充无用字符 E

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

}

 

//  计算检验和(各字节相加,再取反)

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);

}

 

// 解析ICMP回应报头

INT DecodeICMPHeader(char *buf, int bytes)

{

    IpHeader       *iphdr = NULL;

    IcmpHeader     *icmphdr = NULL;

    unsigned short  iphdrlen;

    DWORD           tick;

 

    tick = GetTickCount();

    iphdr = (IpHeader *)buf;

    // Number of 32-bit words * 4 = bytes

    iphdrlen = iphdr->h_len * 4;

    // 回应的包字节不够

    if (bytes  < (iphdrlen + 8)) return -1;

    icmphdr = (IcmpHeader*)(buf + iphdrlen);

    // 回应类型表示未成功

    if (icmphdr->i_type != 0) return -1;

    // 唯一标识号不匹配,别人的包

    if (icmphdr->i_id != (USHORT)GetCurrentProcessId()) return -1;

   

    // 返回耗费时间,毫秒

    return tick - icmphdr->timestamp;

}

 

INT  Ping(LPSTR IP)

{

    WSADATA            wsaData;

    SOCKET             sockRaw;

    sockaddr_in        dest;

    INT                bread,

                       datasize = 32,   // 默认包大小

                       timeout  = 1000; // 超时时间

    CHAR              *icmp_data = NULL,

                      *recvbuf = NULL;

    USHORT             seq_no = 0;

 

    if (WSAStartup(MAKEWORD(2, 2), &wsaData) != 0) return -1;

    sockRaw = WSASocket (AF_INET, SOCK_RAW, IPPROTO_ICMP, NULL, 0, WSA_FLAG_OVERLAPPED);

    if (sockRaw == INVALID_SOCKET)

    {

        if (WSAGetLastError() == 10013) 

        { 

            WSACleanup();

            return -2;  // 创建原始套接字权限不够

        }

        else{ 

            WSACleanup();

            return -3;  // 未知错误

        }

       

    }

 

    bread = setsockopt(sockRaw, SOL_SOCKET, SO_RCVTIMEO, (char*)&timeout, sizeof(timeout));

    if(bread == SOCKET_ERROR)

    {

        closesocket(sockRaw);

        WSACleanup();

        return -4;   // 设置套接字选项失败

    }

    bread = setsockopt(sockRaw, SOL_SOCKET, SO_SNDTIMEO, (char*)&timeout, sizeof(timeout));

    if(bread == SOCKET_ERROR)

    {

        closesocket(sockRaw);

        WSACleanup();

        return -4;   // 设置套接字选项失败

    }

    memset(&dest, 0, sizeof(dest));

    dest.sin_family = AF_INET;

    dest.sin_addr.S_un.S_addr = inet_addr(IP);

 

    datasize += sizeof(IcmpHeader);

 

    icmp_data = (char *)HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY,1024);

    recvbuf = (char *)HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY,1024);

    if (!icmp_data)

    {

        closesocket(sockRaw);

        WSACleanup();

        return -5;  // 堆内存分配失败

    }

    if (!recvbuf)  

    {

        HeapFree(GetProcessHeap(), 0, recvbuf);

        closesocket(sockRaw);

        WSACleanup();

        return -5;  // 堆内存分配失败

    }

   

    memset(icmp_data,0,1024);

    FillICMPData(icmp_data,datasize);

 

    INT nCount,utime;  // 尝试 ping 4次

    for (nCount = 0;nCount != 4; nCount++)

    {

        INT bwrote;

        ((IcmpHeader*)icmp_data)->i_cksum = 0;  // 检验和置零

        ((IcmpHeader*)icmp_data)->i_seq = seq_no++;  // ICMP包序列号

        // 返回从操作系统启动到现在所经过的毫秒数

        ((IcmpHeader*)icmp_data)->timestamp = GetTickCount(); // 本地发送时间戳

        // 计算检验和(注意这里,一定要最后计算,哈哈~我为了让时间更准确,就犯了这个错误)

        ((IcmpHeader*)icmp_data)->i_cksum = checksum((USHORT*)icmp_data, datasize);

 

        bwrote = sendto(sockRaw, icmp_data, datasize, 0, (sockaddr*)&dest, sizeof(dest));

        if (bwrote == SOCKET_ERROR)

        {

            if (WSAGetLastError() == WSAETIMEDOUT)  // 超时

                continue;

            HeapFree(GetProcessHeap(), 0, recvbuf);

            HeapFree(GetProcessHeap(), 0, icmp_data);

            closesocket(sockRaw);

            WSACleanup();

            return -6;   // 发送ICMP报头失败

        }

        bread = recv(sockRaw, recvbuf, 1024, 0);

        if (bread == SOCKET_ERROR)

        {

            if (WSAGetLastError() == WSAETIMEDOUT)  // 超时

                continue;

            HeapFree(GetProcessHeap(), 0, recvbuf);

            HeapFree(GetProcessHeap(), 0, icmp_data);

            closesocket(sockRaw);

            WSACleanup();

            return -7;   // 接收ICMP回应失败

        }

        utime = DecodeICMPHeader(recvbuf,bread);

        if (utime != -1)

            break;

        Sleep(300);

    }

 

    closesocket(sockRaw);

    HeapFree(GetProcessHeap(), 0, recvbuf);

    HeapFree(GetProcessHeap(), 0, icmp_data);

    WSACleanup();

    if(nCount == 4)

        return -8;  // 超时

    else

        return utime;  // 成功,返回耗时

}

 


 

   使用原始套接字需要管理员权限.不然就会返回10013错误代码.

windows下用C语言实现ping 右击生成的ping.exe文件,以管理员身份运行才能不会包10013错误等其他错误。// PingSock.cpp : 定义控制台应用程序的入口点。 // #include #include #pragma comment(lib,"ws2_32.lib") #include //定义默认缓冲区长度 #define DEF_BUF_SIZE 1024 #define IP_HEADER_SI 阅读详情

相关推荐

利用Winsock进行IP通信编程

1 关于WinSockWindows Sockets (即Winsock)是在Windows上进行网络通信编程的API接口,也是Windows网络编程的事实标准。Winsock建立在Berkeley套接口之上, 包括了大量的Unix环境下开发的Berkeley函数,提供了习惯于Unix套接口编程的程序员极为熟悉的环境,并且简化了移植现有的基于套接口的应用程序源代码的工作。另外,Winsock还

armman的专栏 1704

Winsock编程接口实验:实现ping

书上的代码,根据自己的理解对书上代码进行了一部分的更改,并尝试在一些地方使用C++改写。改进程序实现能同时对多个域名进行解析 《Windows网络编程(第2版)》 #define _WINSOCK_DEPRECATED_NO_WARNINGS #include <winsock2.h> #pragma comment(lib, "Ws2_32.lib") #include<iostream> #include<sstream> using namespace s

Mr_atopos的博客 1215

计算机网络作业-winsock写的ping实现

我的作业 需要写作业的可以参考

C/C++:Winsock网络编程—ping命令的简单实现

Winsock网络编程—ping命令的简单实现 前言 先声明 博主实现的是Windows平台的ping命令的简单实现,没有做域名解析,只能直接ping ip。我们要实现ping 肯定得先知道ping的实现原理,ping 发送的 ICMP报文。实际上的落脚点 就是对 ICMP协议和IP协议 结构的学习 以及 如何使用Winsock API 来实现ICMP报文的组包和解包。需要使用wireshark ...

重庆李四 5543

用winsock设计简化的ping应用程序

相当完整的一份winsock设计ping应用程序的文档。你值得拥有。

C语言:Winsock网络编程—ping命令的简单实现 示例demo

C语言:Winsock网络编程—ping命令的简单实现 示例demo https://blog.youkuaiyun.com/qq_29542611/article/details/84452298

winsock 自己写个ping 程序

#include "stdafx.h"#include #include #pragma comment(lib,"Ws2_32.lib")void InitSocket(){ WORD wVersionRequested; WSADATA wsaData; int err; wVersionRequested = MAKEWORD( 2, 2 ); err = WSAStartup( w

CrazyCoder 2091

用Winsock2.0实现Ping命令

学习后Winsock2.0后,写的Ping命令实现,又不对的地方还望大家指正!

c语言实现ping程序

基础知识 1、ICMP协议 互联网控制信息协议(Internet CONTROLM essage Protocol),用于错误报告和调试。该协议是TCP/IP 协议集中的一个子协议,属于网络层协议,主要用于在主机与路由器之间传递控制信息,包括报告错误、交换受限控制和状态信息等。当遇到IP 数据无法访问目标、IP 路由器无法按当前的传输速率转发数据包等情况时,会自动发送ICMP消息。我们可以通过...

ヾ(^∀^)ノ 1万+

一个用winsock2写的ping程序

用winsock2实现的ping程序,介绍了raw socket的用法,以及ICMP协议。

VB6通断程序

给大家分享一个很好的VB6检查网络通断的程序。

能Ping通,能DNS解析,不能打开网页的解决办法

1.Ping地址正常,能ping通任何本来就可以ping通地址,如网关、域名。 2.能DNS解析域名。 3.无法打开网页,感觉是网页打开的一瞬间就显示无网络连接。 4.只需要连接ip地址、无需dns接些的程序都是无法连接,如QQ. 折腾了很久,通过重启路由、sfc修复命令、重装驱动、更换网络等方式修复均无果,郁闷了,只好启动很久以前安装在移动硬盘中的备用系统,结果发现在该系统下,网络正常。不知怎么...

Zola的博客 1万+

别再写爬虫了!用Trae平台5分钟搞定一个能聊天的网页数据抓取Agent

本文介绍了如何利用Trae平台快速构建无需编程的网页数据抓取智能体,实现对话式数据采集。通过自然语言指令,用户可在5分钟内完成从数据抓取到分析的全流程,显著降低技术门槛和维护成本。文章详细解析了Trae智能体的核心能力,包括自然语言理解、智能页面解析、数据清洗和可视化配置,并提供了多个实战案例,展示其在竞品监控和舆情分析中的高效应用。

weixin_29038303的博客 717

01Ping程序的设计

1.Ping程序设计具体设计任务 1.1 实验目的 PING程序是我们使用的比较多的用于测试网络连通性的程序。PING程序基于ICMP,使用ICMP的回送请求和回送应答来工作。由计算机网络课程知道,ICMP是基于IP的一个协议,ICMP包通过IP的封装之后传递。 课程设计中选取PING程序的设计,其目的是希望同学们通过PING程序的设计,能初步掌握TCP/IP网络协议的基本实现方法...

MarkLee0419的博客 2488

告别手绘!用Aseprite+Unity Tilemap,从AI生成到2D游戏地图的保姆级搭建流程

本文详细介绍了如何利用Aseprite和Unity Tilemap从AI生成素材到搭建2D游戏地图的完整流程。涵盖AI生成素材的预处理、图层管理、动画制作,以及Unity中的Tilemap系统配置和性能优化技巧,帮助开发者高效创建像素风游戏地图。

weixin_29015483的博客 580

VS2022下C# WPF项目一键打包成独立exe的完整指南

本文提供了一份在Visual Studio 2022中将C# WPF项目一键打包成独立可执行exe文件的完整指南。通过配置项目属性、启用单文件发布和自包含模式,开发者无需依赖第三方工具,即可生成可在未安装.NET运行时的电脑上直接运行的独立程序,极大简化了桌面应用的分发流程。

weixin_28831399的博客 670

C++代码实现网络Ping功能

ping(Packet Internet Groper)分组网间探测。 测试网络连接的主机或路由器之间的连通性。 应用层使用ICMP协议(网际控制报文协议,Internet Control Message Protocol),必须封装在IP协议里统一收发。

菜鸟打怪的博客 1万+

C++面向对象程序设计大作业:魔兽世界(三):开战

C++面向对象程序设计大作业:魔兽世界(三):开战问题描述问题分析代码 问题描述 问题来自于北京大学郭炜老师的C++慕课的大作业 魔兽世界的西面是红魔军的司令部,东面是蓝魔军的司令部。两个司令部之间是依次排列的若干城市,城市从西向东依次编号为1,2,3 … N ( N <= 20)。红魔军的司令部算作编号为0的城市,蓝魔军的司令部算作编号为N+1的城市。司令部有生命元,用于制造武士。 两军的司令部都会制造武士。武士一共有dragon 、ninja、iceman、lion、wolf 五种。每种武士都有

RedRum_1965的博客 4036

常见问题:"winsock损坏导致可以ping通Ip地址,但是不能上网"的案例

问题描述 可以ping通IP地址,但是不能上网 问题描述 不能上网,但是可以ping通其他主机IP地址 表现如下 C:\\Documents and Settings\\Cr@zy_Bear>ping 202.115.14.151 Pinging ? with 32 bytes of data: ...

kalogen的专栏 496

Claude Code 使用 OpenAI Codex(GPT-5.3-Codex)完整配置教程

通过 LiteLLM 可以让 Claude Code 调用任何模型,包括:OpenAIDeepSeekGemini本地模型↓↓优点:不依赖 Anthropic API可自由切换模型支持统一 AI Gateway这种“LLM Gateway 架构”正在成为 AI 开发工具的主流实践。

Jacobe_zhao的博客 1万+

Rockchip平台Android相机HAL3开发实战:从配置到调试全流程解析

本文深入解析了Rockchip平台Android相机HAL3的开发全流程。从理解AAL与PSL核心架构、解析关键配置文件(如camera3_profiles.xml和Tuning文件),到搭建编译环境、进行增量部署,并提供了系统日志分析、V4L2调试等高级问题排查技巧,为开发者提供了一套从配置到调试的实战指南。

docker7nomad的博客 843

wince 下cmd ping命令的执行

<br />#include <winsock2.h><br />#include <iphlpapi.h><br />#pragma comment(lib, "iphlpapi.lib")<br />#include <icmpapi.h><br /><br />void Ctest111Dlg::CEPing(CString cIPAddr,CListBox * pListBox,UINT uiTimes)//CWnd * pWnd ,<br />{<br /> WSAData wsaData;<br

ljd_1986413的专栏 4505

华为OD机试 - 第k个排列 - 全排列递归(Python/JS/C/C++ 2025 C卷 100分)

给定参数n,从1到n会有n个整数:1,2,3,…,n,这n个数字共有n!按大小顺序升序列出所有排列的情况,并一一标记当n=3时,所有排列如下“123”,“132,“213”,“231”,“312”,“321”输入两行,第一行为n,第二行为k,给定n的范围是[1,9],给定k的范围是[1,n!排列为“12”和“21”,第2个是“21”。给定n和k,返回第k个排列。输出排在第k位置的数字。只有一个排列,直接返回。

学Java,找哪吒 982

Windows ping "General failure."

Windows ping 返回 “General failure” 常规失败,没有网络,无法上网,这时候也许只需要使用管理员权限启动CMD并执行netsh reset winsock即可修复。

2万+

A2A 协议详解:Agent Card 的设计与实现

Agent Card 是 Agent2Agent (A2A) 协议中实现智能体发现与互操作性的核心组件。本文将深入剖析 Agent Card 的设计理念、关键字段及其在智能体生态系统中的作用。我们将通过详细的 JSON Schema 解析和 Python SDK 示例,帮助您理解如何精确地定义和发布智能体能力,为构建可发现、可协作的 AI 智能体奠定基础。当您使用a2a.Agent类初始化一个智能体时,SDK 会根据您提供的参数(nameversion等)自动构建内部的 Agent Card 表示。

加入“Super Entity”,与全能开发团队共探AI智能体与数字人项目,开启前沿技术之旅。 1476

Probability and Statistics - 4th edition

Probability and Statistics - 4th edition

上一篇: 「多播」WinSock下基于IP协议的多播实现示例
下一篇: 「RSA」非对称加密算法--C++实现
TypeCool
博客等级 码龄22年 58粉丝 93原创
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

个

红包个数最小为10个

元

红包金额最低5元

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

抵扣说明:

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

余额充值