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 card
		while (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;
			//可能网卡有多IP
			IP_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 card
		while (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;
			//可能网卡有多IP
			IP_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()
{
	// 初始化socket
	WSADATA 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 条目。

感谢大家阅读

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

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

音视频——码率、帧率越高越清晰?分辨率、像素、dpi的关系

一 前言 本期我介绍一下视频的一些基础概念&#xff0c;如帧率、码率、分辨率、像素、dpi、视频帧、I帧、P帧、gop等。我i初步学习音视频&#xff0c;给这些专业词汇进行扫盲 会解释多少码率是清晰的&#xff0c;是否帧率越高越流畅等问题。 这些概念是比较杂乱的&#xff0c…

CentOS 7镜像下载 以及 DVD ISO 和 Minimal ISO 等各版本的区别介绍

1.官网下载 官网下载地址&#xff1a;官网下载链接 点击进入下载页面&#xff0c;随便选择一个下载即可&#xff08;不推荐&#xff0c;推荐阿里云下载&#xff0c;见下文&#xff09; 阿里云下载站点&#xff08;速度非常快推荐&#xff09; 阿里云下载链接&#xff1a; http…

二叉树(上)——“数据结构与算法”

各位CSDN的uu们好呀&#xff0c;好久没有更新我的数据结构与算法专栏啦&#xff0c;今天&#xff0c;小雅兰继续来更新二叉树的内容&#xff0c;下面&#xff0c;让我们进入链式二叉树的世界吧&#xff01;&#xff01;&#xff01; 二叉树链式结构的实现 二叉树链式结构的实现…

MySQL进阶SQL语句(二)

MySQL进阶SQL语句&#xff08;二&#xff09; 一、MySQL进阶SQL语句1.1 连接查询1.2 CREATE VIEW视图&#xff0c;可以被当作是虚拟表或存储查询1.3 UNION 联集1.4 CASE1.5 空值(NULL) 和 无值() 的区别1.6 正则表达式 二、存储过程2.1 存储过程定义2.2 存储过程的优点2.3 存储…

【数据结构】栈和队列详解

⭐️ 往期相关文章 ✨链接1&#xff1a;数据结构和算法的概念以及时间复杂度空间复杂度详解 ✨链接2&#xff1a;【数据结构】手撕顺序表 ✨链接3&#xff1a;【数据结构】手撕单链表 ✨链接4&#xff1a;【数据结构】双向带头循环链表 ⭐️ 栈和队列 &#x1f320; 栈 栈是…

OpenCV对图片进行缩放处理

在下面的代码中,我会为你优化和解释这段程序: #include <opencv2/opencv.hpp>using namespace cv;int main() {// 读取源图片Mat srcImage = imread("../51_resize.jpg"

目标检测学习

目录 1、目标定位 2、特征点检测 3、目标检测 4、滑动窗口的卷积实现 5、Bounding Box 预测&#xff08;Bounding box predictions&#xff09; 6、交并化 7、非极大值抑制 8、Anchor Boxes 9、YOLO算法 1、目标定位 2、特征点检测 如何检测特征点&#xff08;以人的部…

HTML5新特性总结

新增语义化标签 新增了很多语义化标签&#xff0c;如header、footer、nav、article、section(页面中的某段文字&#xff0c;或文章中的某段文字)、aside、main 其中article标签里可以包含多个section&#xff1b; section强调的是分段或分块&#xff0c;若想将一块内容分成几…

【Vscode】解决 An SSH installation couldn‘t be found

【Vscode】解决 An SSH installation couldn‘t be found 背景描述&#xff1a;在vscode中使用ssh进行连接到时候&#xff0c;已经安装了ssh romote的plugin插件&#xff0c;但是在输入了ssh连接命令之后&#xff0c;仍然出现报错&#xff1a;an ssh installation could not be…

OpenCV 入门教程:中值滤波和双边滤波

OpenCV 入门教程&#xff1a;中值滤波和双边滤波 导语一、中值滤波二、双边滤波三、示例应用3.1 图像去噪3.2 图像平滑 总结 导语 在图像处理和计算机视觉领域&#xff0c;中值滤波和双边滤波是两种常见的滤波方法&#xff0c;用于平滑图像、去除噪声等。 OpenCV 提供了中值滤…

sap abap,forms,smartforms 导出pdf

4种方法&#xff1a; 1.安装pdf程序&#xff0c;Foxit Reader,先敲回车 自动带出&#xff0c;如下图&#xff1a; 直接打印就会弹出保存pdf文档路径&#xff0c;点保存。这种方式是最简单的&#xff0c;可 forms 和 smartforms 。 2. forms 和 smartforms 打印到spool 中&…

Maven工程开发中的继承与聚合

1. 聚合工程概念 设置一个空的maven工程&#xff0c;工程里面只有pom文件&#xff0c;另外将这个工程的打包方式设置为pom。 在聚合工程里面添加聚合工程里面管理的模块 2.聚合总结 3.继承 例如下面02工程继承上面的01工程&#xff0c;在02工程的pom文件中要配置要继承的父工…

保护你的JavaScript代码:深入了解JS混淆加密及其特点

当涉及到JavaScript代码的保护和隐藏时&#xff0c;混淆加密是一种常见的技术。它通过对代码进行转换和重组&#xff0c;使其难以理解和逆向工程。以下是JS混淆加密的几个特点以及它们各自的优缺点&#xff1a; 变量和函数名压缩&#xff1a; 特点&#xff1a;将代码中的变量和…

Hystrix熔断器

雪崩 当山坡积雪内部的内聚力抗拒不了它所受到的重力拉引时&#xff0c;积雪便向下滑动&#xff0c;引起⼤量雪体崩塌&#xff0c;人们把这种自然现象称作雪崩 微服务中&#xff0c;一个请求可能需要多个微服务接口才能实现&#xff0c;会形成复杂的调用链路 …

Holoens证书过期

1. 删除Assets\WSATestCertificate.pfx证书文件。 2. 在Player Settings的Publishing Settings下找到Certificate,选择一个有效的证书。 3. 如果没有其他有效证书,需要生成一个新的测试证书: - Windows: MakeCert.exe -r -pe -n "CNTemporary Certificate" -ss MY …

Linux--操作系统进程的状态

【Linux】进程概念 —— 进程状态_linux d状态进程_Hello_World_213的博客-CSDN博客 新建&#xff1a;字面意思&#xff0c;将你的task_struct创建出来并且还未入队列 运行&#xff1a;task_struct结构体在运行队列中排队&#xff0c;就叫做运行态 阻塞&#xff1a; 等待非C…

GPT(Generative Pre-Training)论文解读及实现(一)

1 GPT Framework 1.1 Unsupervised pre-training Given an unsupervised corpus of tokens U {u1, . . . , un}, we use a standard language modeling objective to maximize the following likelihood: 在给定语料上下文环境下&#xff0c;目标时最大化下面的语言模型&…

OpenCV 图像处理算法和技术的应用实践

OpenCV 图像处理算法和技术的应用实践 导语一、图像滤波算法二、图像分割技术三、特征提取与描述算法四、实践示例&#xff1a;图像风格转换总结 导语 图像处理算法和技术在计算机视觉和图像处理领域发挥着重要作用&#xff0c;通过对图像进行分析、增强和转换&#xff0c;可以…

实验二 常用网络命令

文章目录 实验目的实验原理1. 通过 ping 命令检测网络故障2. ipconfig 命令3. arp 命令4. tracert 命令5. netstat 命令 实验内容1. ping命令2. ipconfig命令3. arp命令 实验总结 实验目的 了解常用网络命令及其使用方法。通过网络命令了解网络状态&#xff0c;并利用网络命令…

高速入门知识02:降低串扰和维持信号完整性的布线方法

文章目录 前言一、单端走线布线1.1.带有短截线的菊花链布线1.2.没有短截线的菊花链布线1.3.星型布线1.4.蛇型布线 二、差分走线布线 前言 串扰是并行走线间不需要的信号耦合。微带线和带状线正确的布线和叠层布局能够降低串扰。 双带线布局有两个靠近的信号层&#xff0c;为降…