3

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();
    }

}`

4

3 に答える 3

1

あなたの問題には 2 つの原因が考えられます。

  1. 設計内の各応答クライアントからの応答ごとに 100 ミリ秒の遅延が組み込まれているようです。BeginReceive メソッドで最初に行うことは、データの有無に関係なく、スリープすることです。応答ごとに、(正しい) BeginReceive を呼び出して、新しい受信コールバックを登録します。ただし、一度に登録される ReceiveCallback は 1 つだけであるため、各応答の処理には少なくとも 100 ミリ秒かかります。同時に 30 件のクライアント コールを受信した場合、最後のコールは 3 秒遅れます。

  2. ReceiveCallback で、メソッド OnFoundDevice を呼び出します。これは、コールバックまたはイベント ハンドラーのように見えます。このコールバックで実行時間がかかると、次に処理される回答が遅れます。コールバックに 1 分かかる場合、次の応答は 1 分 (さらに BeginReceive メソッドで 100 ミリ秒) 遅れます。

推奨される解決策: 1. 次のように、BeginReceive から遅延と条件を削除します。

public void BeginReceive()
{
     sock.BeginReceive(new AsyncCallback(ReceiveCallback), udpState);
}
  1. OnFoundDevice によって行われた作業を確認します。時間がかかる場合は、呼び出しを別のスレッドにマーシャリングします (たとえば、スレッドプールで QueueUserWorkItem を実行します)。

BeginReceive でスリープを使用した理由が、データのリッスンをいつ停止するかの基準を見つけることであった場合、代わりに Start メソッドでタイマーを起動し、所定の時間後またはデータを受信して​​いないときにソケットで Close を呼び出すことができます。設定された期間内。

これがお役に立てば幸いです。

于 2011-09-05T08:01:46.110 に答える
1

なぜあなたが必要なのThread.Sleepですか?

遅延の原因となる場合があります。

于 2011-05-17T07:42:42.540 に答える
0

代わりに、このようなブロッキング呼び出しでタイムアウトを使用できます...とにかく待機している間、プログラムは他の作業をしたくないように見えるため..この方法で、応答が100ミリ秒未満で来る場合は、そうする必要はありませんそんなに待って。

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.
于 2014-09-27T00:04:46.037 に答える