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

ИИ поможет Вам:


  • решить любую задачу по программированию
  • объяснить код
  • расставить комментарии в коде
  • и т.д
Попробуйте бесплатно

Оцени полезность:

7   голосов , оценка 3.857 из 5
Похожие ответы