2014-04-29 3 views
1

현재 SNMP 프린터 모니터 소프트웨어에 대한 자동 검색 기능을 개발 중입니다. 특정 IP 주소의 장치가 포트 9100에 응답하는지 확인하기 위해 범위의 IP를 검사하는 여러 스레드에서 실행되는 도우미 메서드가 필요합니다.이 메서드는 포트 9100에 실제로 응답합니다. SNMP 요청.IP 주소 및 포트가 응답하는지 확인하십시오.

나는 이것이 올바른 접근 방법인지, 그리고 컨텍스트에 따라이 컨텍스트에서 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; 
     } 

설정은 효과가 없습니다.

답변

1

컴퓨터/프린터가 특정 포트의 특정 IP에서 온라인 상태인지 확인하는 올바른 방법입니다. 개체에서 사용중인 메모리를 해제하려면 dispose 메서드를 호출해야합니다. Socket 클래스는 IDisposable을 구현하므로 using을 사용하고 dispoch를 호출하는 것에 대해 걱정하지 않으려면 using을 사용하는 것이 가장 좋습니다.

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

소켓 클래스에는 ReceiveTimeout 및 SendTimeout 속성이 있습니다.

+0

'Dispose'는 "개체에서 사용중인 메모리를 해제하지 않습니다". Dispose는 관리되지 않는 * 자원을 해제하기위한 것입니다. 그래,이 경우에는 관리되지 않는 메모리 버퍼가 포함될 수 있지만 실제로 개체가 사용하는 메모리는 포함되지 않습니다. 이 메모리는 필요한 경우 향후 시점에서 GC에 의해 릴리스됩니다. –

+0

귀하의 기여에 감사드립니다. IDisposable의 Socket 클래스 구현을 활용하고 시간 제한 값을 추가하기 위해 메서드를 다시 작성했습니다. 그러나, 후자는 효과가없는 것으로 보인다. 이 메소드는 15 초가 지난 후에 결과를 리턴합니다 (기본 시간 초과 값으로 의심됩니다). – MartinChristensen

1

이렇게하려면 멀티 스레딩을 사용할 필요가 없습니다. 어쨌든 I/O 작업이 완료 될 때까지 기다리는 스레드를 묶어두고 있습니다. 대신 비동기 I/O를 사용하지 않는 이유는 무엇입니까? (Task.Delay 타이머, 정말 필요하지를 사용),하지만, 쓰기 이해하고 사용하기 쉽고, 그것은 불필요하게 스레드를 낭비하지 않는 시간 제한 메커니즘이 다소 낭비 -

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<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로 데이터를 쉽게 업데이트 할 수 있습니다.