Welcome to OGeek Q&A Community for programmer and developer-Open, Learning and Share
Welcome To Ask or Share your Answers For Others

Categories

0 votes
115 views
in Technique[技术] by (71.8m points)

c# - UDP Server Freezes

I am developing a UDP server that sends a time value over LAN to clients that periodically query the server every 250ms. There is an alarm that sounds when the time hits zero on the client-end, so all clients must receive the message at as close to the same time as possible.

To make this happen, I have a listening function that listens for clients and pushes their endpoints to a queue.

Every 250ms with a System.Windows.Forms.Timer, each client is sent the current time value and their endpoint dequeued.

Problem: the server application unpredictably freezes every so often. Both the server and client applications can be closed and opened with no problems. Sometimes the server will run just fine for days at a time and then just suddenly freeze.

My attempted solutions: try + catching and using() anything that has to do with a socket, adding send and receive timeouts for all sockets depending on their function. Would switching to a TCP protocol better suit this use case?

Inside server form load:

        this.clientEPs = new Queue<IPEndPoint>();

        Thread listener = new Thread(this.listen);
        listener.IsBackground = true;
        listener.Start();

        timer.Start();

Server listening thread:

        private void listen()
        {
            IPEndPoint clientEP = new IPEndPoint(IPAddress.Any, 0);

            while (true)
            {
                try
                {
                    

                    using (UdpClient listener = new UdpClient(LISTENPORT))
                    {
                            listener.Client.ReceiveTimeout = 1000;

                        try
                        {
                            while (true)
                            {

                                listener.Receive(ref clientEP);

                                this.mutex.WaitOne();
                                this.clientEPs.Enqueue(clientEP);
                                this.mutex.ReleaseMutex();
                                
                            }
                        }

                        catch (Exception e)
                        {
                            Console.WriteLine(e.ToString());
                        }
                        finally
                        {
                            listener.Close();
                        }
                    }
                }
                catch (Exception exc)
                {
                    Console.WriteLine(exc.ToString());
                }
            } 
        }

Server relay function:

        private void relay()
        {

            this.mutex.WaitOne();

            try
            {
                using (UdpClient relayer = new UdpClient(RELAYPORT))
                {
                        relayer.Client.SendTimeout = 1000;

                    try
                    {
                        while (this.clientEPs.Count > 0)
                        {

                            relayer.Send(this.messageBytes, this.messageBytes.Length, this.clientEPs.Peek());


                            this.clientEPs.Dequeue();
                            

                        }
                    }

                    catch (Exception e)
                    {
                        Console.WriteLine(e.ToString());
                    }
                    finally
                    {
                        relayer.Close();
                    }
                }
            }
            catch (Exception exc)
            {
                Console.WriteLine(exc.ToString());
            }

            this.mutex.ReleaseMutex();


        }

Server relay ticker:

        private void timer_Tick(object sender, EventArgs e)
        {
            string message = DateTime.Now.ToString();
            this.messageBytes = Encoding.Unicode.GetBytes(JsonConvert.SerializeObject(message));

            this.relay();
        }

Client initalization in form load.

Thread communicator = new Thread(this.communicate);
communicator.IsBackground = true;
communicator.Start();

this.time = new string();

Client query thread:

        private void communicate()
        {

            IPEndPoint serverEP = new IPEndPoint(IPAddress.Any, 0);
            string serverMessage;
            byte[] clientMessage = Encoding.Unicode.GetBytes("Please send the current time.");

            while (true)
            {
                try
                {

                    using (UdpClient client = new UdpClient(CLIENTPORT))
                    {
                        try
                        {
                            client.Client.SendTimeout = 1000;
                            client.Client.ReceiveTimeout = 1000;

                            

                            while (true)
                            {

                                client.Send(clientMessage, clientMessage.Length, SERVERIP, SERVERPORT);

                                serverMessage = Encoding.Unicode.GetString(client.Receive(ref serverEP));

                                this.currentTime = serverMessage;

                                
                                if (message == null)
                                    throw new Exception();

                                
                                if (isTimeZero(this.currentTime))
                                {
                                    SoundPlayer sp = new SoundPlayer("resources\audio\BEEP.wav");
                                    sp.Play();
                                }

                            }
                        }
                        catch (Exception e)
                        {
                            Console.WriteLine(e.ToString());

                          
                        }
                        finally
                        {
                            client.Close();
                            Thread.Sleep(250);
                        }
                    }
                }
                catch (Exception exc)
                {
                    Console.WriteLine(exc.ToString());
                }
            }      
        }

P.S. I am a newbie to networking in general and any critiques/advice would be greatly appreciated! Thank you!

question from:https://stackoverflow.com/questions/65920116/udp-server-freezes

与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…
Welcome To Ask or Share your Answers For Others

1 Reply

0 votes
by (71.8m points)
Waitting for answers

与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…
OGeek|极客中国-欢迎来到极客的世界,一个免费开放的程序员编程交流平台!开放,进步,分享!让技术改变生活,让极客改变未来! Welcome to OGeek Q&A Community for programmer and developer-Open, Learning and Share
Click Here to Ask a Question

...