2012-08-09 3 views
0

ALL, C#에서 비동기 소켓을 사용하고 있습니다. 내 문제는 : 정보를 서버로 즉시 보내야하기 때문에 연결을 완료하기 위해 콜백을 기다리고 싶습니다.비동기 소켓에서 연결을 기다리는 것이 가능합니까?

class InternetConnector 
{ 
    private struct ConnectionData 
    { 
     public Action<Exception> ErrorHandler { get; set; } 
     public Socket Socket { get; set; } 
    } 
    public void ConnectToHost(Action<Exception> errorHandler) 
    { 
     IPEndPoint ip = new IPEndPoint(IPAddress.Parse(connector_host), connector_port); 
     client = new Socket(AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.Tcp); 
     var ConnectionData = new ConnectionData { ErrorHandler = errorHandler, Socket = client }; 
     client.Blocking = true; 
     client.BeginConnect(ip, new AsyncCallback(ConnectCallback), ConnectionData); 
     connectDone.WaitOne(100); 
    } 

    private static void ConnectCallback(IAsyncResult ar) 
    { 
     ConnectionData connectionData = new ConnectionData(); 
     try 
     { 
      connectionData = (ConnectionData)ar.AsyncState; 
      connectionData.Socket.EndConnect(ar); 
      connectDone.Set(); 
      Connected = true; 
     } 
     catch (Exception e) 
     { 
      if (connectionData.ErrorHandler != null) 
       connectionData.ErrorHandler(e); 
     } 
    } 
} 

public partial class Form1 : Form 
{ 
    private bool isRunning = false; 
    private InternetConnector client = new InternetConnector(); 

    private void AsyncErrorHandler(Exception e) 
    { 
     if (status.InvokeRequired) 
     { 
      status.BeginInvoke(new Action(() => AsyncErrorHandler(e))); 
      return; 
     } 
     InternetConnector.Connected = false; 
     isRunning = false; 
     startStop.Text = "Start"; 
     status.ForeColor = Color.Red; 
     status.Text = "Socket Error: " + e.Message; 
    } 

    private void startStop_Click(object sender, EventArgs e) 
    { 
     if (!isRunning || !InternetConnector.Connected) 
     { 
      if (!InternetConnector.Connected) 
      { 
       client.SetAddress(ipAddress.Text); 
       client.SetPort(Convert.ToInt32(connectionport.Text)); 
       client.ConnectToHost(AsyncErrorHandler); 
       status.Text = "Signals Receiver: Connected"; 
       status.ForeColor = Color.Green; 
       startStop.Text = "Stop"; 
       isRunning = true; 
    // if connection successful, send some data and start reading the socket 
      } 
      else 
      { 
       startStop.Text = "Start"; 
       client.DisconnectFromHost(AsyncErrorHandler); 
       isRunning = false; 
      } 
     } 
    } 
} 

내가 관련하여 예외를 처리 할 수 ​​있습니다 : 여기

는 코드입니다. 이제 성공적인 연결을 처리해야합니다.

감사합니다.

답변

1

당신은 성공뿐만 아니라 오류에 호출 할 같은 패턴을 따르고, 핸들러를 제공 할 수

class InternetConnector 
{ 
    private struct ConnectionData 
    { 
     public Action<Socket> SuccessHandler { get; set; } 
     public Action<Exception> ErrorHandler { get; set; } 
     public Socket Socket { get; set; } 
    } 

    public void ConnectToHost(Action<Socket> successHandler, Action<Exception> errorHandler) 
    { 
     IPEndPoint ip = new IPEndPoint(IPAddress.Parse(connector_host), connector_port); 
     client = new Socket(AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.Tcp); 
     var ConnectionData = new ConnectionData 
     { 
      SuccessHandler = successHandler, 
      ErrorHandler = errorHandler, 
      Socket = client 
     }; 
     client.Blocking = true; 
     client.BeginConnect(ip, new AsyncCallback(ConnectCallback), connectionData); // <-- make sure to use the lower-case connectionData here! :) 
     connectDone.WaitOne(100); 
    } 

    private static void ConnectCallback(IAsyncResult ar) 
    { 
     ConnectionData connectionData = new ConnectionData(); 
     try 
     { 
      connectionData = (ConnectionData)ar.AsyncState; 
      connectionData.Socket.EndConnect(ar); 
      connectDone.Set(); 
      Connected = true; 
      if (connectionData.SuccessHandler != null) 
       connectionData.SuccessHandler(connectionData.Socket); 
     } 
     catch (Exception e) 
     { 
      if (connectionData.ErrorHandler != null) 
       connectionData.ErrorHandler(e); 
     } 
    } 
} 

성공 핸들러가 Action<Socket> 위임 일치해야합니다 당신이 전달하는 함수의 서명, 이는 다음과 같이 보일 것입니다 :

void MySuccessHandler(Socket socket) 
{ 
    // do stuff with the connected socket..   
    Console.WriteLine("Connected to {0}", socket.RemoteEndPoint);   
} 

void MyErrorHandler(Exception e) 
{ 
    Console.WriteLine("Connection error {0}", e.Message);   
} 

... 

myConnector.ConnectToHost(MySuccessHandler, MyErrorHandler); 
관련 문제