gpt4 book ai didi

c# - 取消异步套接字操作

转载 作者:太空宇宙 更新时间:2023-11-03 20:36:38 38 4
gpt4 key购买 nike

我有一个 C# .Net 3.5 应用程序,它向可能订阅特定多播组的任何人发送多播“Hello”数据包,然后监听所有响应。因此,每隔 X 秒,我可能会发送一个“Hello”数据包并记下每个响应者。

它旨在像这样使用:

MulticastHello hello_ = new MulticastHello();

// alert our UI of any responses to the 'Hello'
hello_.ReceivedHelloResponse += OnHelloResponse;

// this timer function is triggered every X seconds
private void OnTimer(object sender, EventArgs e)
{
// stop listening for responses to the last 'hello'
hello_.CancelHello();

// send a new 'hello' and start listening for responses
hello_.SendHello("224.0.100.1");
}

不幸的是,我在取消异步读取时遇到了问题。我的 private void OnReceive(IAsyncResult ar) 函数偶尔会抛出一个 System.ArgumentException,指出“IAsyncResult 对象未从此类的相应异步方法返回。”

如何可靠地取消异步套接字操作。或者,有更好的方法吗?

我的实现如下。

谢谢,保罗H

public class HelloResponseEventArgs : EventArgs { /*...*/ }

public class MulticastHello : IDisposable
{
public event EventHandler<HelloResponseEventArgs> ReceivedHelloResponse;

private Socket socket_;

private byte[] received_ = new byte[HelloResponse.Size];

private EndPoint responder_ = new IPEndPoint(IPAddress.Any, 0);

protected virtual void OnReceivedHelloResponse(HelloResponseEventArgs e)
{
EventHandler<HelloResponseEventArgs> evt = ReceivedHelloResponse;
if (null != evt)
evt(this, e);
}

private void OnReceive(IAsyncResult ar)
{
IPEndPoint ipendpoint = new IPEndPoint(IPAddress.Any, 0);
EndPoint endpoint = ipendpoint as EndPoint;

try
{
socket_.EndReceiveFrom(ar, ref endpoint);
}
catch (System.ObjectDisposedException)
{
// the read was canceled. This is expected.
return;
}

// decode the response and set the event
IPEndPoint remote = endpoint as IPEndPoint;
HelloResponse response = new HelloResponse(Deserialize<HelloPacket>(received_));
OnReceivedHelloResponse(new HelloResponseEventArgs(remote.Address.ToString(), response));

// keep receiving responses until canceled
socket_.BeginReceiveFrom(received_,
0,
received_.Length,
SocketFlags.None,
ref endpoint,
new AsyncCallback(OnReceive),
null);
}

// stop listening for responses to the hello frame
public void CancelHello()
{
if (socket_ != null)
socket_.Close();
}

// send an initial 'Hello' to the a multicast address. Start listening for responses
public void SendHello(string address)
{
socket_ = new Socket(AddressFamily.InterNetwork, SocketType.Dgram, ProtocolType.Udp);
socket_.MulticastLoopback = false;
socket_.Ttl = 255;

HelloResponse send = new HelloResponse();
byte[] data = Serialize(send.Packet);

EndPoint remote = new IPEndPoint(IPAddress.Parse(address), 7);
socket_.SendTo(data, remote);

socket_.BeginReceiveFrom(received_,
0,
received_.Length,
SocketFlags.None,
ref responder_,
new AsyncCallback(OnReceive),
null);
}

#region IDisposable Members
/* close the socket on dispose*/
#endregion
}

最佳答案

在 BeginReceive 中将套接字作为状态参数发送。即

socket_.BeginReceiveFrom(
received_,
0,
received_.Length,
SocketFlags.None,
ref endpoint,
new AsyncCallback(OnReceive),
socket_);

然后在 OnReceive 中使用它来代替类变量 socket。即

Socket socket = (Socket)ar.AsyncState;
socket.EndReceiveFrom(ar, ref endpoint);

这确保 EndReceiveFrom 调用发生在调用 BeginReceive 的同一个套接字上。然后正如 PaulH 提到的那样,只需捕获 OnReceive 中的 ObjectDisposedException,这将是在套接字上调用 Close() 的信号。

-奥利

关于c# - 取消异步套接字操作,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/4799391/

38 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com