如何检查我是否已连接?

ALL,我正在编写一个需要与服务器进行异步阻塞连接的应用程序。 我有一个带有按钮的GUI表单和一个与BeginConnect / EndConnect对执行连接的类。 该实现遵循此 MSDN示例。

但是,在回调方法中抛出了exception。这就是我要避免的。 我想要的是检查是否已建立连接,以及它是否在GUI表单上将相应的错误吐出为文本。

我试图检查BeginConnect()的返回值,但它在调用静态方法之前返回。 我尝试重新抛出exception并在建立连接(按钮单击事件)时捕获它,但它不起作用。 没有抓住例外。

如何检查是否已建立连接?

我可以将我的文本控件传递给连接类,并在捕获exception时将文本设置为错误,但还有其他方法吗?

谢谢。

[编辑]

class InternetConnector { public void ConnectToHost() { IPEndPoint ip = new IPEndPoint(IPAddress.Parse(connector_host), connector_port); client = new Socket(AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.Tcp); client.Blocking = true; client.BeginConnect(ip, new AsyncCallback(ConnectCallback), client); } private static void ConnectCallback(IAsyncResult ar) { try { Socket sock = (Socket)ar.AsyncState; sock.EndConnect(ar); connectDone.Set(); Connected = true; } catch (Exception e) { throw (e); } } } public partial class Form1 : Form { private bool isRunning = false; private InternetConnector client = new InternetConnector(); private void startStop_Click(object sender, EventArgs e) { try { if (!isRunning || !InternetConnector.Connected) { if (!InternetConnector.Connected) { client.SetAddress(ipAddress.Text); client.SetPort(Convert.ToInt32(connectionport.Text)); client.ConnectToHost(); status.Text = "Signals Receiver: Connected"; status.ForeColor = Color.Green; startStop.Text = "Stop"; isRunning = true; } else { startStop.Text = "Start"; client.DisconnectFromHost(); isRunning = false; } } } catch(Exception ex) { status.Text = "Socket Error: " + ex.Message; } } } 

如果我使用“throw(e);” 在回调catch块中,exception未在单击侦听器中捕获。 但是回调中需要try / catch,因为错误连接会引发exception并且不会返回错误。

因为您使用的是异步BeginConnect,所以回调几乎不会发生在与单击处理程序相同的线程上,因此您的单击处理程序无法捕获exception。

如果需要从异步回调设置UI元素的状态,通常需要在创建UI的同一线程上执行委托。

从Control派生的任何UI元素都有一些方法可以帮助您执行此操作( InvokeRequiredBeginInvoke )。 我修改了你的样本以帮助说明这一点。

基本上,您可以传入一个Action委托,如果它出现在async Connect回调中,将被exception调用。 然后,此error handling委托可以执行所有工作,以根据异步连接回调期间引发的exception设置UI状态。

因为我们需要传递error handling委托,所以我们必须创建一个结构(Called ConnectionData)来保存我们需要在异步连接回调中访问的所有状态(套接字和error handling程序)。

 class InternetConnector { private struct ConnectionData { public Action ErrorHandler { get; set; } public Socket Socket { get; set; } } public void ConnectToHost(Action 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); } 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) { // queue a call to ourself on control's UI thread and immediately return status.BeginInvoke(new Action(()=>AsyncErrorHandler(e))); return; } // we are on the right thread to set the status text status.Text = "Async Error: " + ex.Message; } private void startStop_Click(object sender, EventArgs e) { try { if (!isRunning || !InternetConnector.Connected) { if (!InternetConnector.Connected) { client.SetAddress(ipAddress.Text); client.SetPort(Convert.ToInt32(connectionport.Text)); // connect, pass in the method to use for error reporting client.ConnectToHost(AsyncErrorHandler); status.Text = "Signals Receiver: Connected"; status.ForeColor = Color.Green; startStop.Text = "Stop"; isRunning = true; } else { startStop.Text = "Start"; client.DisconnectFromHost(); isRunning = false; } } } catch(Exception ex) { status.Text = "Socket Error: " + ex.Message; } } } 

有属性Socket.Connected 。

在窗户中

返回值

如果没有错误发生,则connect返回零。 否则,它返回SOCKET_ERROR,并且可以通过调用WSAGetLastError来检索特定的错误代码。