При сканировании хостов нужно собрать информацию о них. Все работает, но слишком медленно - 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();
- }
- }
- }
- }
ИИ поможет Вам:
- решить любую задачу по программированию
- объяснить код
- расставить комментарии в коде
- и т.д