windows下使用arp 协议

/
//自动扫描局域网存活主机

本程序是利用arp协议去获取局域网中的存活主机

arp协议概述

地址解析协议,即ARP(Address Resolution Protocol),是根据IP地址获取物理地址的一个TCP/IP协议。主机发送信息时将包含目标IP地址的ARP请求广播到局域网络上的所有主机,并接收返回消息,以此确定目标的物理地址

定义数据结构

这个数据结构位ip和mac对应
typedef struct s_ip_fname
{//一个网卡可能有多个IP地址std::vector<std::string> ips;std::string mac;
}s_ip_fname;
下面的数据结构是为了存储mac地址的
typedef struct list_nim
{atomic<uint32_t> v_n = 0;std::map<std::string,std::string> nim;std::mutex  mutex;void clear(){nim.clear();}void push(string &ip, string &mac){mutex.lock();nim[mac] = ip;mutex.unlock();}
}list_nim;

获取IP地址

获取到本机的IP地址,本例子是可以获取网卡的多个IP地址

std::string main_ip()
{std::vector<s_ip_fname> ip_mac_vector;get_ipfname(ip_mac_vector);std::string ip;if (ip_mac_vector.size() == 0)return ip;auto it = ip_mac_vector.begin();if(it->ips.size()>0)ip = it->ips[0];return ip;
}

其中获取get_ipfname 获取ip地址列表,写成了一个静态函数,我们无论如何都要想到,一个主机不一定只有一个网卡,一个网卡不一定只有一个ip

static int get_ipfname(std::vector<s_ip_fname>& ff)
{
#define ADDR(x) pIpAdapterInfo->Address[x]PIP_ADAPTER_INFO pIpAdapterInfo = new IP_ADAPTER_INFO();unsigned long stSize = sizeof(IP_ADAPTER_INFO);int nRel = GetAdaptersInfo(pIpAdapterInfo, &stSize);DWORD netCardNum = 0;GetNumberOfInterfaces(&netCardNum);int IPnumPerNetCard = 0;if (ERROR_BUFFER_OVERFLOW == nRel){delete pIpAdapterInfo;pIpAdapterInfo = (PIP_ADAPTER_INFO)new BYTE[stSize];nRel = GetAdaptersInfo(pIpAdapterInfo, &stSize);//return -1;}if (ERROR_SUCCESS == nRel){//maybe we have >1 network cardwhile (pIpAdapterInfo){s_ip_fname ipf;switch (pIpAdapterInfo->Type){case MIB_IF_TYPE_OTHER://cout << "OTHER" << endl; break;case MIB_IF_TYPE_ETHERNET://cout << "ETHERNET" << endl; break;case MIB_IF_TYPE_TOKENRING://cout << "TOKENRING" << endl; break;case MIB_IF_TYPE_FDDI://cout << "FDDI" << endl; break;case MIB_IF_TYPE_PPP://cout << "PPP" << endl; break;case MIB_IF_TYPE_LOOPBACK://cout << "LOOPBACK" << endl; break;case MIB_IF_TYPE_SLIP://cout << "SLIP" << endl; break;default://cout << "" << endl; break;}char buffer[128];sprintf(buffer, "%02X-%02X-%02X-%02X-%02X-%02X",//sprintf(buffer, "%02X-%02X-%02X-%02X-%02X-%02X-%02X-%02X",ADDR(0), ADDR(1), ADDR(2), ADDR(3), ADDR(4), ADDR(5));ipf.mac = buffer;IPnumPerNetCard = 0;//可能网卡有多IPIP_ADDR_STRING* pIpAddrString = &(pIpAdapterInfo->IpAddressList);do{ipf.ips.push_back(pIpAddrString->IpAddress.String);pIpAddrString = pIpAddrString->Next;} while (pIpAddrString);ff.push_back(ipf);pIpAdapterInfo = pIpAdapterInfo->Next;}}//释放内存空间if (pIpAdapterInfo){delete pIpAdapterInfo;}return 0;
}

线程函数

改函数启动一个线程,去发送arp请求

	void start_thread(int tn,uint32_t ulNetName){thread th[256];for (int i = 0; i < tn; i++){th[i] = thread([this,ulNetName] {while (1){uint32_t x = v_number--;uint32_t n = htonl(ulNetName + x + 1);this->send_arp(n);if (v_number < 0)break;}});//th.detach();}for (int i = 0; i < tn; i++)th[i].join();}

send arp 函数实际上就是调用windows的辅助函数SendARP

	void send_arp(uint32_t naddr_f){//for (uint32_t t = naddr_f; t < naddr_t; t++)//{struct in_addr in;in.S_un.S_addr = naddr_f;string ip = inet_ntoa(in);std::cout << "scan:";std::cout << ip.c_str() << endl;HRESULT result;ULONG c[2] = { 0 }, len = 6;//unsigned int ipn = htonl(inet_addr(ip.c_str()));//发送ARP包result = SendARP(naddr_f, NULL, c, &len);if (result == NO_ERROR){BYTE *g = (BYTE *)&c;if (len){string strmac(32, 0);sprintf(const_cast<char*>(strmac.c_str()),"%.2X-%.2X-%.2X-%.2X-%.2X-%.2X",g[0], g[1], g[2], g[3], g[4], g[5]);v_lnim.push(strmac, ip);}}//}//return 0;}

目标

//自动扫描局域网存活主机
程序清单,复制可用
/
//自动扫描局域网存活主机
//优点:不用输入ip
//缺点:如果遇到主机多IP只能扫描其中一个

#include <winsock2.h>
#include <stdio.h>
#include <iphlpapi.h>#pragma comment (lib,"ws2_32.lib")  
#pragma comment (lib,"iphlpapi.lib")#include <iostream>
#include <list>
#include <windows.h>
#include <thread>
#include <atomic>
#include <mutex>
#include <map>
#include <vector>
using namespace std;typedef struct s_ip_fname
{//一个网卡可能有多个IP地址std::vector<std::string> ips;std::string mac;
}s_ip_fname;typedef struct list_nim
{atomic<uint32_t> v_n = 0;std::map<std::string,std::string> nim;std::mutex  mutex;void clear(){nim.clear();}void push(string &ip, string &mac){mutex.lock();nim[mac] = ip;mutex.unlock();}
}list_nim;static int get_ipfname(std::vector<s_ip_fname>& ff)
{
#define ADDR(x) pIpAdapterInfo->Address[x]PIP_ADAPTER_INFO pIpAdapterInfo = new IP_ADAPTER_INFO();unsigned long stSize = sizeof(IP_ADAPTER_INFO);int nRel = GetAdaptersInfo(pIpAdapterInfo, &stSize);DWORD netCardNum = 0;GetNumberOfInterfaces(&netCardNum);int IPnumPerNetCard = 0;if (ERROR_BUFFER_OVERFLOW == nRel){delete pIpAdapterInfo;pIpAdapterInfo = (PIP_ADAPTER_INFO)new BYTE[stSize];nRel = GetAdaptersInfo(pIpAdapterInfo, &stSize);//return -1;}if (ERROR_SUCCESS == nRel){//maybe we have >1 network cardwhile (pIpAdapterInfo){s_ip_fname ipf;switch (pIpAdapterInfo->Type){case MIB_IF_TYPE_OTHER://cout << "OTHER" << endl; break;case MIB_IF_TYPE_ETHERNET://cout << "ETHERNET" << endl; break;case MIB_IF_TYPE_TOKENRING://cout << "TOKENRING" << endl; break;case MIB_IF_TYPE_FDDI://cout << "FDDI" << endl; break;case MIB_IF_TYPE_PPP://cout << "PPP" << endl; break;case MIB_IF_TYPE_LOOPBACK://cout << "LOOPBACK" << endl; break;case MIB_IF_TYPE_SLIP://cout << "SLIP" << endl; break;default://cout << "" << endl; break;}char buffer[128];sprintf(buffer, "%02X-%02X-%02X-%02X-%02X-%02X",//sprintf(buffer, "%02X-%02X-%02X-%02X-%02X-%02X-%02X-%02X",ADDR(0), ADDR(1), ADDR(2), ADDR(3), ADDR(4), ADDR(5));ipf.mac = buffer;IPnumPerNetCard = 0;//可能网卡有多IPIP_ADDR_STRING* pIpAddrString = &(pIpAdapterInfo->IpAddressList);do{ipf.ips.push_back(pIpAddrString->IpAddress.String);pIpAddrString = pIpAddrString->Next;} while (pIpAddrString);ff.push_back(ipf);pIpAdapterInfo = pIpAdapterInfo->Next;}}//释放内存空间if (pIpAdapterInfo){delete pIpAdapterInfo;}return 0;
}class c_arp
{list_nim v_lnim;std::atomic<int> v_number = 0;public:~c_arp(){v_lnim.clear();}size_t size(){return v_lnim.nim.size();}void set_max_ip(uint32_t number){v_number = number;}void send_arp(uint32_t naddr_f){//for (uint32_t t = naddr_f; t < naddr_t; t++)//{struct in_addr in;in.S_un.S_addr = naddr_f;string ip = inet_ntoa(in);std::cout << "scan:";std::cout << ip.c_str() << endl;HRESULT result;ULONG c[2] = { 0 }, len = 6;//unsigned int ipn = htonl(inet_addr(ip.c_str()));//发送ARP包result = SendARP(naddr_f, NULL, c, &len);if (result == NO_ERROR){BYTE *g = (BYTE *)&c;if (len){string strmac(32, 0);sprintf(const_cast<char*>(strmac.c_str()),"%.2X-%.2X-%.2X-%.2X-%.2X-%.2X",g[0], g[1], g[2], g[3], g[4], g[5]);v_lnim.push(strmac, ip);}}//}//return 0;}void start_thread(int tn,uint32_t ulNetName){thread th[256];for (int i = 0; i < tn; i++){th[i] = thread([this,ulNetName] {while (1){uint32_t x = v_number--;uint32_t n = htonl(ulNetName + x + 1);this->send_arp(n);if (v_number < 0)break;}});//th.detach();}for (int i = 0; i < tn; i++)th[i].join();}void print(){for (auto iter : v_lnim.nim){std::cout << iter.first.c_str() << ":" << iter.second.c_str() << endl;}}
};std::string main_ip()
{std::vector<s_ip_fname> ip_mac_vector;get_ipfname(ip_mac_vector);std::string ip;if (ip_mac_vector.size() == 0)return ip;auto it = ip_mac_vector.begin();if(it->ips.size()>0)ip = it->ips[0];return ip;
}
int main()
{// 初始化socketWSADATA data;WORD wVersion = MAKEWORD(2, 2);WSAStartup(wVersion, &data);hostent *pLocalHost;
//	HANDLE hEvent;// 获得本机IP结构pLocalHost = ::gethostbyname("");std::string ip = main_ip();// 这样获得是网络字节序//ULONG ulIpAddress = (*(struct in_addr *)*(pLocalHost->h_addr_list)).S_un.S_addr;ULONG ulIpAddress = inet_addr(ip.c_str());PIP_ADAPTER_INFO pAdapterInfo = NULL;ULONG ulLen = 0;// 为适配器结构申请内存::GetAdaptersInfo(pAdapterInfo, &ulLen);pAdapterInfo = (PIP_ADAPTER_INFO)::GlobalAlloc(GPTR, ulLen);c_arp arp;if (::GetAdaptersInfo(pAdapterInfo, &ulLen) == ERROR_SUCCESS){while (pAdapterInfo != NULL){if(ip.compare(pAdapterInfo->IpAddressList.IpAddress.String) == 0)//if (::inet_addr(pAdapterInfo->IpAddressList.IpAddress.String) == ulIpAddress){// 这里要转换为主机字节序ULONG ulIpMask = ntohl(::inet_addr(pAdapterInfo->IpAddressList.IpMask.String));// 与获得网络号ULONG ulNetName = ntohl(ulIpAddress) & ulIpMask;//获得网段内的主机数UINT unNum = ~ulIpMask;UINT nNumofHost = unNum - 2;arp.set_max_ip(nNumofHost);//arp.start_thread(255,ulNetName);for (uint32_t i = 0; i < nNumofHost; i++){uint32_t n = htonl(ulNetName + i + 1);thread th(std::bind(&c_arp::send_arp, &arp, n));th.detach();}break;}pAdapterInfo = pAdapterInfo->Next;}}cout<<arp.size()<<endl;arp.print();getchar();return 0;
}

编译运行,如下图所示:
在这里插入图片描述

windows其他函数

GetIpNetTable 函数检索本地计算机上的 ARP 表,该表将 IPv4 地址映射到物理地址。

CreateIpNetEntry 函数在本地计算机上的 ARP 表中创建 ARP 条目。

DeleteIpNetEntry 函数从本地计算机上的 ARP 表中删除 ARP 条目。

SetIpNetEntry 函数修改本地计算机上的 ARP 表中的现有 ARP 条目。

FlushIpNetTable 函数从本地计算机上的 ARP 表中删除指定接口的所有 ARP 条目。

感谢大家阅读

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.hqwc.cn/news/20344.html

如若内容造成侵权/违法违规/事实不符,请联系编程知识网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

python散记

"""字符串格式化的两种方法"""name"sans" age18 math_score90.56 english_score88.8print(f"这个学生的名字叫{name},年龄{age},数学分数是{math_score},总分是{math_scoreenglish_score}") print("这个学生的名字叫%s…

克服 ClickHouse 运维难题:ByteHouse 水平扩容功能上线

前言 对于分析型数据库产品&#xff0c;通过增加服务节点实现集群水平扩容&#xff0c;并提升集群性能和容量&#xff0c;是运维的必要手段。 但是对于熟悉 ClickHouse 的工程师而言&#xff0c;听到“扩容”二字一定会头疼不已。开源 ClickHouse 的 MPP 架构导致扩容成本高&…

python接口自动化(三十四)-封装与调用--函数和参数化(详解)

简介 前面虽然实现了参数的关联&#xff0c;但是那种只是记流水账的完成功能&#xff0c;不便于维护&#xff0c;也没什么可读性&#xff0c;随着水平和技能的提升&#xff0c;再返回头去看前边写的代码&#xff0c;简直是惨不忍睹那样的代码是初级入门的代码水平都达不到。接下…

杂记:逆向一块FPGA核心板

最近太热了&#xff0c;实在无心看书。阵列书丢一边看不进去&#xff0c;还买了几本统计信号的甚至都没开始看&#xff08;笑&#xff09;&#xff0c;躺在床上玩玩手机摆烂&#xff0c;看到某黄色APP上有老板卖拆机的板子&#xff0c;价格美丽&#xff0c;美中不足的是没有资料…

SpringBoot集成MQTT

官网配置说明 MQTT Supporthttps://docs.spring.io/spring-integration/reference/html/mqtt.html#mqtt Spring integration交互逻辑 对于发布者&#xff1a; 消息通过消息网关发送出去&#xff0c;由 MessageChannel 的实例 DirectChannel 处理发送的细节。DirectChannel …

自动驾驶与智能网联场地测试一体化装备应用

自动化驾驶层级与结构 L1:能够辅助驾驶员玩车某些驾驶任务制动防抱死系统 (ABS),车身电子稳定系统 (ESP)等,这些配置就是L1级别的运用。 L2:部分自动化,在L2的级别里,必须要具备的是自适应巡航系统,主动车道保持系统自动刹车辅助系统以及自动泊车系统等系统。 L3:有条件…

【Android】从零搭建组件化项目

组件化系列文章介绍的内容稍微多了点&#xff0c;本着研究透这玩意的精神&#xff0c;从组件化的简介开始说起。 目录 简介组件化、模块化与插件化开始创建配置共享文件打包模式配置APT与JavaPoet 简介 什么是组件化&#xff1f; 将多个功能模板拆分、重组的过程。 为什么要使…

基于单片机智能衣柜 智能衣橱 换气除湿制系统紫外线消毒的设计与实现

功能介绍 以51单片机作为主控系统&#xff1b;液晶显示当前衣柜温湿度和柜门开启关闭状态&#xff1b;按键设置当前衣柜湿度上限值、衣柜门打开和关闭&#xff0c;杀菌消毒&#xff1b;当湿度超过设置上限&#xff0c;继电器闭合开启风扇进行除湿&#xff1b;进行杀菌消毒时&am…

量子近似优化算法(QAOA)入门(1):从量子绝热算法(QAA)角度的直观理解

文章目录 前言&#xff1a;量子计算的本质是测量一、基于量子逻辑电路的常用算法1.NISQ&#xff1a;Noisy Intermediate-Scale Quantum&#xff08;含噪声中等规模量子&#xff09; 二、量子绝热算法&#xff08;QAA&#xff1a;Quantum Adiabatic Algorithm&#xff09;1.QAA的…

爬虫入门07——requests中携带cookie信息

爬虫入门07——requests中携带cookie信息 对于需要登陆的网站如果不携带cookie是无法获取我们所需内容的就以查看我在CSDN中的订单为例&#xff0c;在登陆后可以查看到订单信息 而当我们使用Python代码发出请求时&#xff0c;是不携带cookie&#xff0c;因此无法拿到订单相关信…

查看某个三方依赖jar包是在哪个pom引入的(springboot+idea)

项目springboot1升级2版本&#xff0c;日志框架使用的是log4j&#xff0c;升级到springboot2版本某些依赖引入了logback依赖包&#xff0c;然后项目启动报错&#xff1a; 查看这个SLF4JLoggerContextFactory这个类是在哪个jar包下 使用idea的maven依赖图查看功能寻找是哪个p…

page_dewarp实现弯曲文本矫正

朋友们&#xff0c;如果你使用ocr&#xff0c;再识别的时候会遇到文本扭曲的问题&#xff0c;为了解决这个问题&#xff0c;需要进行弯曲文本矫正&#xff0c;这里推荐一个开源项目&#xff0c;可以使用上面的功能进行矫正&#xff0c;不过里面可能需要改动一些代码&#xff0c…