做网站视频 上传到哪儿,南宁网站推广营销,建网站问题,淘宝客网站怎么做的C#实现多线程局域网扫描器的思路与具体代码
思路#xff1a;
获取局域网内所有 IP 地址遍历所有 IP 地址#xff0c;使用 Ping 命令测试主机是否在线如果主机在线#xff0c;则扫描主机上的所有端口#xff0c;确定哪些端口是开放的输出扫描结果
在上述过程中#xff0…C#实现多线程局域网扫描器的思路与具体代码
思路
获取局域网内所有 IP 地址遍历所有 IP 地址使用 Ping 命令测试主机是否在线如果主机在线则扫描主机上的所有端口确定哪些端口是开放的输出扫描结果
在上述过程中第 2 步和第 3 步都可以使用多线程来加速。具体来说可以将 IP 地址分成若干段每个线程负责扫描一段 IP 地址。对于每个 IP 地址也可以启动一个线程来扫描其端口。
具体代码
using System;
using System.Collections.Generic;
using System.Diagnostics;
using System.Net;
using System.Net.NetworkInformation;
using System.Net.Sockets;
using System.Threading;namespace LANScanner
{class Program{// 扫描参数static int numThreads 100;static int timeout 100;static void Main(string[] args){// 获取本地 IP 地址和子网掩码IPAddress[] addresses Dns.GetHostAddresses(Dns.GetHostName());IPAddress subnetMask null;foreach (NetworkInterface adapter in NetworkInterface.GetAllNetworkInterfaces()){IPInterfaceProperties properties adapter.GetIPProperties();foreach (UnicastIPAddressInformation addressInfo in properties.UnicastAddresses){if (addressInfo.Address.AddressFamily AddressFamily.InterNetwork){subnetMask addressInfo.IPv4Mask;break;}}if (subnetMask ! null){break;}}// 计算子网地址和广播地址IPAddress subnetAddress GetSubnetAddress(addresses[0], subnetMask);IPAddress broadcastAddress GetBroadcastAddress(addresses[0], subnetMask);// 创建线程池并开始扫描ListWaitHandle handles new ListWaitHandle();ThreadPool.SetMinThreads(numThreads, numThreads);for (int i 1; i 254; i){IPAddress ip GetIPAddress(subnetAddress, i);handles.Add(new ManualResetEvent(false));ThreadPool.QueueUserWorkItem(PingHost, new object[] { ip, handles.Last() });}WaitHandle.WaitAll(handles.ToArray());Console.WriteLine(Scanning complete.);Console.ReadLine();}static void PingHost(object args){// 解析参数object[] parameters (object[])args;IPAddress ip (IPAddress)parameters[0];ManualResetEvent handle (ManualResetEvent)parameters[1];// 测试主机是否在线Ping ping new Ping();PingReply reply ping.Send(ip, timeout);if (reply.Status IPStatus.Success){Console.WriteLine(Host {0} is online., ip);// 扫描主机上的端口ListWaitHandle handles new ListWaitHandle();for (int port 1; port 65535; port){handles.Add(new ManualResetEvent(false));ThreadPool.QueueUserWorkItem(CheckPort, new object[] { ip, port, handles.Last() });}WaitHandle.WaitAll(handles.ToArray());}// 通知主线程完成handle.Set();}static void CheckPort(object args){// 解析参数object[] parameters (object[])args;IPAddress ip (IPAddress)parameters[0];int port (int)parameters[1];ManualResetEvent handle (ManualResetEvent)parameters[2];// 尝试连接端口try{using (TcpClient client new TcpClient()){client.Connect(ip, port);Console.WriteLine(Port {0} is open on host {1}., port, ip);}}catch (Exception){// 端口未打开}// 通知主线程完成handle.Set();}static IPAddress GetSubnetAddress(IPAddress address, IPAddress subnetMask){byte[] addressBytes address.GetAddressBytes();byte[] maskBytes subnetMask.GetAddressBytes();byte[] subnetBytes new byte[4];for (int i 0; i 4; i){subnetBytes[i] (byte)(addressBytes[i] maskBytes[i]);}return new IPAddress(subnetBytes);}static IPAddress GetBroadcastAddress(IPAddress address, IPAddress subnetMask){byte[] addressBytes address.GetAddressBytes();byte[] maskBytes subnetMask.GetAddressBytes();byte[] broadcastBytes new byte[4];for (int i 0; i 4; i){broadcastBytes[i] (byte)(addressBytes[i] | ~maskBytes[i]);}return new IPAddress(broadcastBytes);}static IPAddress GetIPAddress(IPAddress subnetAddress, int host){byte[] subnetBytes subnetAddress.GetAddressBytes();byte[] hostBytes new byte[4];hostBytes[3] (byte)host;byte[] ipBytes new byte[4];for (int i 0; i 4; i){ipBytes[i] (byte)(subnetBytes[i] | hostBytes[i]);}return new IPAddress(ipBytes);}}
}
上述代码实现了一个简单的多线程局域网扫描器支持 Ping 主机和扫描主机端口并输出扫描结果。需要注意的是在实际应用中可能需要对输入进行严格的验证和过滤以确保系统安全。
同时在使用多线程和异步 I/O 操作时也需要注意程序的正确性和健壮性。如果不正确地使用这些技术可能会导致程序出现各种问题例如竞态条件和死锁。因此在使用这些技术时请务必小心并仔细测试程序。
要解决错误“WaitHandles的数量必须小于或等于64”需要将句柄列表拆分为更小的块并使用WaitAll分别等待每个块。例如你可以将句柄列表分成4个块每个块25个句柄然后分别等待每个块:
ListWaitHandle[] handleChunks new ListWaitHandle[4];
for (int i 0; i handleChunks.Length; i)
{handleChunks[i] new ListWaitHandle();
}
for (int i 1; i 254; i)
{// ...int chunkIndex (i - 1) % handleChunks.Length;handleChunks[chunkIndex].Add(new ManualResetEvent(false));ThreadPool.QueueUserWorkItem(PingHost, new object[] { ip, handleChunks[chunkIndex].Last() });
}
for (int i 0; i handleChunks.Length; i)
{WaitHandle.WaitAll(handleChunks[i].ToArray());
}