我正在使用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();
}
}`
答案 0 :(得分:1)
为什么需要Thread.Sleep
?
可能会造成延误。
答案 1 :(得分:1)
我发现了两个可能导致问题的原因。
您的设计中每个响应客户端的每个响应似乎都有100毫秒的延迟。你在BeginReceive方法中做的第一件事是睡觉,无论是否有数据。对于每个响应,您(correclty)调用BeginReceive来注册新的接收回调。但由于一次只注册一个ReceiveCallback,处理每个响应至少需要100 ms。如果您同时收到30个传入的客户端呼叫,则最后一个将延迟3秒。
在ReceiveCallback中,您可以调用方法OnFoundDevice。这看起来像一个回调或事件处理程序。此回调所花费的任何执行时间都将延迟下一个已处理的答案。如果回调需要1分钟,则下一个响应将延迟1分钟(在BeginReceive方法中加上100毫秒)。
建议的解决方案: 1.从BeginReceive中删除延迟和条件,如下所示。
public void BeginReceive()
{
sock.BeginReceive(new AsyncCallback(ReceiveCallback), udpState);
}
如果你在BeginReceive中使用sleep的原因是找到何时停止监听数据的标准,你可以在Start方法中为此启动一个计时器,并在预定时间后或在没有预定时间时在套接字上调用Close。在设定的时间范围内收到数据。
我希望这可以帮助你。
答案 2 :(得分:0)
你可以使用像这样的阻止调用超时...因为看起来你的程序在它等待的时候不想做任何其他的工作..这样如果响应时间不到100毫秒你就不会# 39; t必须等那么久。
udpAdmin.Client.SetSocketOption(SocketOptionLevel.Socket, SocketOptionName.ReceiveTimeout, 100)
receiveBytes = sock.Receive(RemoteIpEndPoint) 'waits here till you get a response or until timeout, whichever comes first.