UDPClient Async BeginReceive 非常慢
我正在使用 UDPClient 发送多播请求并接收来自网络上各个客户端的响应。我能够发送请求并获得响应,但我得到的响应非常慢。需要 2-3 分钟才能得到所有客户的回复。在我检查 WireShark 的网络上发送请求时,我仅在测试程序中看到来自所有客户端的毫秒响应。这需要很多时间。谁能指导我可能会犯什么错误?以下是代码。请指导我。过去两天我一直被这个问题困扰。
public class Trinity_WSDiscovery : IDiscoveryService
{
#region IDiscoveryService Members
public event EventHandler FoundNewDevice;
public event EventHandler EndOfDiscovery;
DeviceBinding m_DeviceBinding;
bool IsFindComplete = false;
Thread receiveThread;
UdpClient sock ;
IPEndPoint RemoteIpEndPoint = new IPEndPoint(System.Net.IPAddress.Any, 0);
IPEndPoint iep = new IPEndPoint(System.Net.IPAddress.Parse("239.255.255.250"), 3702);
UdpState udpState = new UdpState();
XmlDocument xmlDoc = new XmlDocument();
public void Start()
{
//Need to create new object every time we start discovery because
//every time udp buffer needs to be flushed and restarted
sock = new UdpClient();
string str = "<?xml version='1.0' encoding='utf-8'?><soap:Envelope xmlns:soap=\"http://www.w3.org/2003/05/soap-envelope\" xmlns:d=\"http://schemas.xmlsoap.org/ws/2005/04/discovery\" xmlns:wsadis=\"http://schemas.xmlsoap.org/ws/2004/08/addressing\" xmlns:dn=\"http://www.onvif.org/ver10/network/wsdl\"><soap:Header><wsadis:MessageID>uuid:" + System.Guid.NewGuid().ToString() + "</wsadis:MessageID><wsadis:To>urn:schemas-xmlsoap-org:ws:2005:04:discovery</wsadis:To><wsadis:Action>http://schemas.xmlsoap.org/ws/2005/04/discovery/Probe</wsadis:Action></soap:Header><soap:Body><d:Probe><d:Types /> <d:Scopes/></d:Probe></soap:Body></soap:Envelope>";
byte[] data = Encoding.ASCII.GetBytes(str);
sock.Send(data, data.Length, iep);
sock.JoinMulticastGroup(System.Net.IPAddress.Parse("239.255.255.250"));
IPEndPoint iep1 = new IPEndPoint(System.Net.IPAddress.Any, 0);
udpState.ipEndpt = RemoteIpEndPoint;
udpState.udpClient = sock;
BeginReceive();
}
public void BeginReceive()
{
Thread.Sleep(100);
if (sock.Available > 0)
{
sock.BeginReceive(new AsyncCallback(ReceiveCallback), udpState);
}
else
{
FindComplete();
}
}
public void ReceiveCallback(IAsyncResult ar)
{
UdpClient udpClient = (UdpClient)((UdpState)(ar.AsyncState)).udpClient;
IPEndPoint ipEndpt = (IPEndPoint)((UdpState)(ar.AsyncState)).ipEndpt;
Byte[] receiveBytes = udpClient.EndReceive(ar, ref ipEndpt);
string receiveString = Encoding.ASCII.GetString(receiveBytes);
if (receiveString.Contains("NetworkVideoTransmitter"))
{
xmlDoc.LoadXml(receiveString);
XmlNodeList list = xmlDoc.GetElementsByTagName("XAddrs", "http://schemas.xmlsoap.org/ws/2005/04/discovery");
XmlNode node = list[0];
string strEndPoints = node.FirstChild.Value;
string[] strEndPointList = Regex.Split(strEndPoints, " ");
OnFoundDevice(strEndPointList);
}
BeginReceive();
}
}`
I am using UDPClient to send multicast request and receive response from various clients on the network. I am able to send request and also getting response, but response that I get is very slow. It take 2-3 minutes to get response from all the clients. On send request on the network I checked in the WireShark, there I am seeing response in milliseconds from all the clients only in test program. It is taking lot of time. Can anyone guide what mistake I might be doing? Following is the code. Please guide me on this. I have been stuck on this issue for the last 2 days.
public class Trinity_WSDiscovery : IDiscoveryService
{
#region IDiscoveryService Members
public event EventHandler FoundNewDevice;
public event EventHandler EndOfDiscovery;
DeviceBinding m_DeviceBinding;
bool IsFindComplete = false;
Thread receiveThread;
UdpClient sock ;
IPEndPoint RemoteIpEndPoint = new IPEndPoint(System.Net.IPAddress.Any, 0);
IPEndPoint iep = new IPEndPoint(System.Net.IPAddress.Parse("239.255.255.250"), 3702);
UdpState udpState = new UdpState();
XmlDocument xmlDoc = new XmlDocument();
public void Start()
{
//Need to create new object every time we start discovery because
//every time udp buffer needs to be flushed and restarted
sock = new UdpClient();
string str = "<?xml version='1.0' encoding='utf-8'?><soap:Envelope xmlns:soap=\"http://www.w3.org/2003/05/soap-envelope\" xmlns:d=\"http://schemas.xmlsoap.org/ws/2005/04/discovery\" xmlns:wsadis=\"http://schemas.xmlsoap.org/ws/2004/08/addressing\" xmlns:dn=\"http://www.onvif.org/ver10/network/wsdl\"><soap:Header><wsadis:MessageID>uuid:" + System.Guid.NewGuid().ToString() + "</wsadis:MessageID><wsadis:To>urn:schemas-xmlsoap-org:ws:2005:04:discovery</wsadis:To><wsadis:Action>http://schemas.xmlsoap.org/ws/2005/04/discovery/Probe</wsadis:Action></soap:Header><soap:Body><d:Probe><d:Types /> <d:Scopes/></d:Probe></soap:Body></soap:Envelope>";
byte[] data = Encoding.ASCII.GetBytes(str);
sock.Send(data, data.Length, iep);
sock.JoinMulticastGroup(System.Net.IPAddress.Parse("239.255.255.250"));
IPEndPoint iep1 = new IPEndPoint(System.Net.IPAddress.Any, 0);
udpState.ipEndpt = RemoteIpEndPoint;
udpState.udpClient = sock;
BeginReceive();
}
public void BeginReceive()
{
Thread.Sleep(100);
if (sock.Available > 0)
{
sock.BeginReceive(new AsyncCallback(ReceiveCallback), udpState);
}
else
{
FindComplete();
}
}
public void ReceiveCallback(IAsyncResult ar)
{
UdpClient udpClient = (UdpClient)((UdpState)(ar.AsyncState)).udpClient;
IPEndPoint ipEndpt = (IPEndPoint)((UdpState)(ar.AsyncState)).ipEndpt;
Byte[] receiveBytes = udpClient.EndReceive(ar, ref ipEndpt);
string receiveString = Encoding.ASCII.GetString(receiveBytes);
if (receiveString.Contains("NetworkVideoTransmitter"))
{
xmlDoc.LoadXml(receiveString);
XmlNodeList list = xmlDoc.GetElementsByTagName("XAddrs", "http://schemas.xmlsoap.org/ws/2005/04/discovery");
XmlNode node = list[0];
string strEndPoints = node.FirstChild.Value;
string[] strEndPointList = Regex.Split(strEndPoints, " ");
OnFoundDevice(strEndPointList);
}
BeginReceive();
}
}`
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(3)
为什么需要Thread.Sleep?
这可能会导致延误。
Why do you need
Thread.Sleep
?It might cause the delays.
我发现您的问题有两个可能的原因。
看来您在设计中为每个响应客户端的每个响应内置了 100 毫秒的延迟。在 BeginReceive 方法中,您要做的第一件事就是休眠,无论是否有数据。对于每个响应,您(正确地)调用 BeginReceive 来注册新的接收回调。但由于一次只注册一个 ReceiveCallback,因此处理每个响应至少需要 100 毫秒。如果您同时收到 30 个传入客户端调用,则最后一个客户端调用将延迟 3 秒。
在 ReceiveCallback 中,您调用方法 OnFoundDevice。这看起来像回调或事件处理程序。此回调花费的任何执行时间都会延迟下一个处理的答案。如果回调需要 1 分钟,则下一个响应将延迟 1 分钟(在 BeginReceive 方法中加上 100 毫秒)。
建议的解决方案:
1. 从 BeginReceive 中删除延迟和条件,如下所示。
如果您在 BeginReceive 中使用 sleep 的原因是为了找到何时停止侦听数据的标准,您可以在 Start 方法中为此启动一个计时器,并在预定时间后或未接收到数据时在套接字上调用 Close在设定的时间范围内。
我希望这对你有帮助。
I see two possible causes for your problem.
It seems as you have built in a 100 ms delay for each response from each responding client in your design. The first thing you do in your BeginReceive method is to sleep, regardless if there is data or not. For each response, you (correclty) call BeginReceive to register your new receive callback. But since there is only one ReceiveCallback registered at a time, processing each response will take at least 100 ms. If you get 30 incoming client calls at the same time, the last one will thus be delayed 3 seconds.
In your ReceiveCallback you call your method OnFoundDevice. This looks like a callback or event handler. Any execution time spent by this callback will delay the next processed answer. If the callback takes 1 minute, the next response will be delayed 1 minute (plus 100 ms in your BeginReceive method).
Suggested solution:
1. Remove delay and condition from your BeginReceive, like this.
If the reason you used sleep in your BeginReceive was to find a criteria on when to stop listening for data, you could launch a timer for this instead in your Start method and call Close on your socket after a predetermined time or when not having received data within a set timespan.
I hope this helps you out.
您可以使用像这样的阻塞调用超时...因为看起来您的程序在等待时不想做任何其他工作..这样,如果响应时间少于 100 毫秒,您就不必这样做等那么久。
you could use a timeout with a blocking call like this instead... because it appears your program does not want to do any other work whilst it waits anyway.. this way if the response comes in less than 100ms you don't have to wait that long.