簡體   English   中英

檢查IP地址和端口是否響應

[英]Check if IP Address and Port are responding

我目前正在為SNMP打印機監控器軟件開發自動發現功能。 我需要一個助手方法,該方法由多個線程執行,每個線程都檢查一個范圍內的ip,以確定某個ip地址處的設備是否正在響應端口9100,從而確定它實際上是打印機,然后再發送向它的SNMP請求。

我結束了下面的方法,但是我不知道這是否是正確的方法,並且按照慣例它是否在此上下文中正確使用了Close()方法(我可以看到Dispose(),Disconnect()和Shutdown()方法也可用,該使用哪一個? 此外,我需要設置最大超時值。 5秒,因此在呈現結果之前,線程不會停留太長時間。 到目前為止,我的代碼:

private bool GetTCPPrinterResponse(IPAddress _ip)
{
        int port = 9100;

        bool isResponsive = false;

        Socket s = new Socket(AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.Tcp);

        try
        {
            s.Connect(_ip, port);

            isResponsive = true;
        }
        catch (SocketException)
        {
            isResponsive = false;
        }
        finally
        {
            s.Close();
        }

        return isResponsive;
    }

方法編輯后:

private bool GetTCPPrinterResponse(IPAddress _ip)
        {
            int port = 9100;

            bool isResponsive = false;

            using (Socket s = new Socket(AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.Tcp))
            {
                s.ReceiveTimeout = 3000;
                s.SendTimeout = 3000;

                try
                {
                    s.Connect(_ip, port);

                    isResponsive = true;
                }
                catch (SocketException)
                {
                    isResponsive = false;
                }
            }

            return isResponsive;
        }

設置超時屬性無效。

這是檢查計算機/打印機是否在某個端口上的某個IP上在線的正確方法。 您應該調用dispose方法來釋放對象正在使用的內存。 套接字類實現IDisposable,因此最好是使用using而不用擔心調用dispose,因為using會為您實現。

using(Socket s = new Socket(AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.Tcp))
{
//...
}

套接字類具有屬性ReceiveTimeout和SendTimeout。

無需為此使用多線程。 您正在捆綁線程,這些線程最終將始終等待I / O操作完成。 相反,為什么不使用異步I / O?

public async Task<Tuple<IPAddress, bool>> GetResponse(IPAddress address)
{
  using (var client = new TcpClient(AddressFamily.InterNetwork))
  {
    var connectTask = client.ConnectAsync(address, 80);

    await Task.WhenAny(connectTask, Task.Delay(5000));

    if (connectTask.IsCompleted)
        return Tuple.Create(address, true);
    else
        return Tuple.Create(address, false);
  }
}

可以進一步改善-超時機制有點浪費( Task.Delay使用計時器,不是真正必要的),但是它易於編寫,理解和使用,並且不會不必要地浪費線程。

呼叫將如下所示:

Task<Tuple<IPAddress, bool>>[] tasks = 
    new []
    {
      GetResponse(Dns.GetHostAddresses("www.google.com").First()),
      GetResponse(Dns.GetHostAddresses("www.microsoft.com").First()),
      GetResponse(Dns.GetHostAddresses("www.yahoo.com").First()),
      GetResponse(Dns.GetHostAddresses("www.altavista.com").First()),
    };

Task.WhenAll(tasks).Wait();

foreach (var t in tasks)
    t.Result.Dump(); // t.Result has the IP address and status

這將等待所有設備響應(或超時)。 當然,沒有什么可以阻止您以更具交互性的方式執行此操作-您可以像返回數據一樣輕松地更新UI。

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM