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;
}
}
}
}
我可以在连接中处理异常。现在我也需要处理成功的连接。
谢谢。
答案 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);