是否可以等待异步套接字上的连接

时间:2012-08-09 01:23:37

标签: c# sockets asynchronous

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 个答案:

答案 0 :(得分:2)

您可以遵循相同的模式,并提供一个处理程序,以便在成功和错误时调用:

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);