MFC 로 기본적인 네트워크 프로그래밍만 하다가 C# 네트워크 프로그래밍을 하려니 막히는게 조금 있다...

알다싶이 Socket 에는 Send, Receive 할 때의 Timeout 값을 설정할 수 있다. 하지만 Connect 할 때 Timeout 값을 설정하는 옵션은 없다. 아무런 조치 없이 Connect 할 때 원격지에 연결할 수 없는 상황이 되면 25 ~ 30 초간 Block 상태가 되버린다. google 검색하다가 codeproject 의 article 을 보고 공부할 겸 적어보았다.






Implementation of Connecting a Socket with Timeout in C#



Introduction

여러분도 알다싶이 System.Net.Sockets.TcpClientSystem.Net.Sockets.Socket 클래스는 Socket 에 연결하기 위한 Timeout 값을 가지지 않는다. 하지만 Timeout 값을 설정할 수 있는 방법이 있다. .Net Socket 은 동기/비동기 소켓 연결중에 Connect/BeginConnect 메소드를 호출할 때 Connect Timeout 을 지원하지 않는다. 대신 connect 는 서버 연결에 listening  되지 않거나 어떠한 네트워크 에러로 예외가 전달되기 전에는 매우 긴 시간을 기다리게 한다. 보통 20 ~ 30 초간 기다리게 된다. socket 라이브러리에 SocketOptionName.SendTimeout 이라는 옵션이 있는데 이는 최초의 connect 가 아닌 데이터를 Send 할 때 사용되어지는 옵션이다.



Using the Code

이 기능은 클래스로 구현되어있다. 클래스의 내용은 아래와 같다.



ManualResetEvent 를 이용하는 것이 로직의 핵심이다. ManualResetEvent 는 WaitOne 메소드를 가지고 있는데 오버로드된 WaitOne(TimeSpan, Boolean) 를 이용하였다. MSDN 에 따르면 WaitOne(TimeSpan, Boolean) 메소드는 현재 인스턴스가 signal 신호를 받을때 까지 현재 스레드를 블록시킨다. TimeSpan 을 이용하여 시간 간격을 지정할 수 있으며 기다리기 전에 동기적 도메인에서 빠져나올지를 지정할 수 있다.

메인 스레드에서 timeout 시간까지 또는 스레드 이벤트에 TimeoutObject.Set() 을 이용한 신호를 받을 때 까지  메인 스레드를 블록 시키기 위해 TimeoutObject.WaitOne(timeoutMsec, false) 를 호출한다. WaitOne 메소드는 timeout 값에 의해 블록해제되었을 때 false 를 리턴하며 TimeoutException 을 발생시킨다. 반면에 성공적으로 소켓이 연결되었거나 어떠한 네트워크적 에러로 인해 연결이 실패 되었을 때 true 를 리턴한다.

TcpClient BeginConnect 메소드는 블록되지 않는 비동기 메소드 이다. BeginConnect 메소드를 호출한 후에, WaitOne 을 사용하여 비동기적으로 수행한 콜백 메서드의 결과를 기다리게 된다. 만약 BeginConnect 메소드의 동작이 timeout 시간 안에 완료되지 못한다면, WaitOne 메소드는 신호를 받고, TimeoutException 을 리턴받는다. 만약 BeginConnect 메소드의 동작이 timeout 시간 안에 완료 된다면 CallBackMethod 에서 TimeoutObject.Set() 메소드로 ManualResetEvent 에 신호를 줄것이다. CallBackMethod BeginInvoke 로 delegate 로써 전달시킨 것이다. BeginInvoke 는 동작이 완료되었을 때 Invoke 시키기 위해 CallBackMethod 를 참조한다. 



원문 : http://www.codeproject.com/KB/IP/TimeOutSocket.aspx
Posted by six605
,