При сканировании хостов нужно собрать информацию о них. Все работает, но слишком медленно - C#
Формулировка задачи:
Разработал систему мониторинга. При сканировании хостов нужно собрать информацию о них. Все работает, но слишком медленно. Компьютеров несколько тысяч, а один выключенный компьютер сканируется полторы минуты.
Можно ли как-то уменьшить время сканирования одного порта, которое равно ~21сек. Вещи типа SendTimeout и ReceiveTimeout не помогают. Пробовал сканировать порты с помощью асинхронных сокетов с таймаутом 3 секунды, работает хорошо, однако операционая система по истечени этого времени все равно продолжает ждать ответ. В итоге сканирутся в 50 потоков, а висит их 50 и постоянно увеличивается.
Код обычного сканера:
Код с асинхронными сокетами
struct PortScanStructure { public bool Active; public bool PortOpen; } class PortScannerOld { public static void Scan(string p_IPAddress, int p_Port, ref PortScanStructure p_PSS) { p_PSS.Active = false; p_PSS.PortOpen = false; Socket sock; sock = new Socket(AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.Tcp); sock.ReceiveTimeout = 500; sock.SendTimeout = 100; try { sock.Connect(p_IPAddress, p_Port); } catch (SocketException se) { if (se.ErrorCode == 10061 || se.ErrorCode == 10054) p_PSS.Active = true; } finally { if (sock.Connected) { p_PSS.Active = true; p_PSS.PortOpen = true; sock.Disconnect(false); } sock.Close(); } } }
struct PortScanResult { public bool PortActive; public bool HostActive; public PortScanResult(bool PortState, bool HostState) { PortActive = PortState; HostActive = HostState; } } class PortScanner { private ManualResetEvent TimeoutObject = new ManualResetEvent(false); private PortScanResult Result = new PortScanResult(false, false); public PortScanner() { } ~PortScanner() { TimeoutObject.Close(); } public PortScanResult Scan(string host, int port, int timeout) { TimeoutObject.Reset(); Socket sock = new Socket(AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.Tcp); sock.BeginConnect(host, port, ConnectCallback, sock); TimeoutObject.WaitOne(timeout, false); return Result; } public void ConnectCallback(IAsyncResult AsyncResult) { Socket sock = (Socket)AsyncResult.AsyncState; try { sock.EndConnect(AsyncResult); if (sock.Connected) { sock.Shutdown(SocketShutdown.Both); sock.Disconnect(false); Result.PortActive = true; Result.HostActive = true; } } catch (SocketException se) { if (se.ErrorCode == 10054 || se.ErrorCode == 10061) { Result.PortActive = false; Result.HostActive = true; } } catch { } finally { sock.Close(); TimeoutObject.Set(); } } }
Решение задачи: «При сканировании хостов нужно собрать информацию о них. Все работает, но слишком медленно»
textual
Листинг программы
using System; using System.Collections.Generic; using System.Linq; using System.Text; using System.Net; using System.Net.Sockets; using System.Threading; namespace portScan2 { class Program { static void Main(string[] args) { PortScanner ps = new PortScanner(); ps.Scan("192.168.0.1", 23, 1000); ps.Scan("192.168.0.1", 80, 1000); ps.Scan("192.168.0.1", 135, 1000); ps.Scan("192.168.0.1", 443, 1000); ps.Scan("192.168.0.1", 8080, 1000); Console.WriteLine("--->"); Console.Read(); } } struct PortScanResult { public bool PortActive; public bool HostActive; public PortScanResult(bool PortState, bool HostState) { PortActive = PortState; HostActive = HostState; } } class PortScanner { private ManualResetEvent TimeoutObject = new ManualResetEvent(false); private PortScanResult Result = new PortScanResult(false, false); public PortScanner() { } ~PortScanner() { TimeoutObject.Close(); } public PortScanResult Scan(string host, int port, int timeout) { TimeoutObject.Reset(); Socket sock = new Socket(AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.Tcp); sock.BeginConnect(host, port, ConnectCallback, sock); TimeoutObject.WaitOne(timeout, false); sock.Close(); Console.WriteLine("Scan complete"); return Result; } public void ConnectCallback(IAsyncResult AsyncResult) { Socket sock = (Socket)AsyncResult.AsyncState; try { sock.EndConnect(AsyncResult); if (sock.Connected) { sock.Shutdown(SocketShutdown.Both); sock.Disconnect(false); Result.PortActive = true; Result.HostActive = true; } } catch (SocketException se) { if (se.ErrorCode == 10054 || se.ErrorCode == 10061) { Result.PortActive = false; Result.HostActive = true; } } catch { } finally { sock.Close(); TimeoutObject.Set(); } } } }
ИИ поможет Вам:
- решить любую задачу по программированию
- объяснить код
- расставить комментарии в коде
- и т.д