소켓 연결 시간 제한 - 두 번째 이야기
예전에 한번 소개해 드렸지요.
소켓 연결 시간 제한
; https://www.sysnet.pe.kr/2/0/629
위의 방식이 동작 자체는 잘 하는데, 한 가지 마음에 안 드는 점이 있더군요. ^^ 바로 정상적인 연결이 될 만한 상황에서도 다음과 같은 '예외'가 Output 창에 발생한다는 점입니다.
A first chance exception of type 'System.Net.Sockets.SocketException' occurred in System.dll
Connect 메서드 호출 시점에 "Would block"을 알리는 방법으로 '예외'를 사용하기 때문인데요. 이 때문에 try/catch로 예외를 감싸서 Exception.ToString을 해보면 다음과 같은 예외 메시지를 얻을 수 있습니다.
A non-blocking socket operation could not be completed immediately
경우에 따라서는 대수롭지 않게 넘어갈 수 있지만, 복잡한 소켓 프로그램을 만들 때는 "Output" 창에 "System.Net.Sockets.SocketException" 메시지가 보인다는 것 자체가 문제의 소지가 있기 때문에 예외를 없애려는 노력을 하게 되는데, 이 과정에서 디버깅을 용이하게 하기 위해 "System.Net.Sockets.SocketException" 예외에서 디버거를 멈추도록 설정하는 경우 "Would block" 예외에서까지 실행이 멈춰버리기 때문에 은근히 불편하다는 문제가 있습니다.
그래서, 개선의 여지가 필요할 것 같아서... 잠시 생각을 한 끝에 .NET 자체의 비동기 메서드로 처리하는 것이 좋겠다는 생각이 들었습니다. ^^ 다음과 같이!
class Program
{
static void Main(string[] args)
{
using (Socket socket = ConnectWithTimeout("www.jennifersoft.com", 85, 2)) // 2초 내에 연결되지 않으면 실패로 간주!
{
if (socket == null)
{
Console.WriteLine("Not Connected");
}
else
{
Console.WriteLine("Connected");
}
}
}
static Socket ConnectWithTimeout(string host, int port, int timeoutSecond)
{
Socket socket = null;
try
{
socket = new Socket(AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.Tcp);
IAsyncResult result = socket.BeginConnect(host, port, (ar) =>
{
try
{
socket.EndConnect(ar);
}
catch { }
}, null);
if (result.AsyncWaitHandle.WaitOne(TimeSpan.FromSeconds(timeoutSecond)) == false)
{
socket.Close();
return null;
}
if (socket.Connected == true)
{
return socket;
}
}
catch (SocketException)
{
}
if (socket != null)
{
socket.Close();
}
return null;
}
}
어떠세요? 그런대로... 괜찮은 것 같죠? ^^
(
첨부된 파일은 위의 코드를 포함한 예제 프로젝트입니다.)
[이 글에 대해서 여러분들과 의견을 공유하고 싶습니다. 틀리거나 미흡한 부분 또는 의문 사항이 있으시면 언제든 댓글 남겨주십시오.]