使用udp C#发送和接收数据时丢失一些数据 [英] loss some data when send and recieve data using udp C#

查看:102
本文介绍了使用udp C#发送和接收数据时丢失一些数据的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

大家好

我不知道这个论坛是否适合写我的问题。

i don't know if this forum is right place to write my question or not.

我在我的电脑上创建app以使用udp协议发送和接收数据。我使用代码来监控我的服务器上的数据接收,并且从我的电脑发送时发现一些数据丢失。

i create app on my pc to send and receive data using udp protocol. i use code to monitor data recieving on my server and i found some data lossing when sending from my pc.

我试图长时间解决这个问题但是我摔倒了

I'm trying to solve this issue for long time but i fall

我的电脑上网连接是fiper光纤下载(60 Mbps)上传(15Mbps)

my pc internet connection is fiper optic download (60 Mbps) upload (15Mbps)

任何人都可以帮我解决这个问题问题并节省我的时间,请?

这些是我在电脑上使用的代码

Can anyone help me to fix this problem and save my time, please?
these are codes that i use on my pc

发送代码:

code of sending:

        public async Task LinesAsPara(LineCollection Lines)
        {
            CancelTask = false;
            taskToken = new CancellationTokenSource();
            CancellationToken ct = taskToken.Token;

            if (Monitor.IsEntered(syncObj))
            {
                paused = false;
                Monitor.Exit(syncObj);
            }

            WatchTest.Start();

            Task task = new Task(() => {
                foreach (var Oneline in ltlTextArea.TextArea.Lines)
                {

                    try
                    {

                        CheckForIllegalCrossThreadCalls = false;

                        string pattern = @"(?:CACHE PEER|cache peer):\s*(\S+)+\s+(\d*)";

                        foreach (Match m in Regex.Matches(Oneline.Text, pattern))
                        {
                            Server = Dns.GetHostAddresses(m.Groups[1].Value)[0];
                            RemotePort = Convert.ToInt32(m.Groups[2].Value);
                            CachePeer = m.Groups[0].Value;
                        }

                        IPEndPoint ipeSender = new IPEndPoint(Server, RemotePort);
                        //The epSender identifies the incoming clients
                        EndPoint epSender = (EndPoint)ipeSender;

                        int ID = 0;
                        byte[] buf = new byte[32];
                        buf[0] = TYPE_PINGREQ;

                        // Self Program Use
                        buf[1] = 0x4D;
                        buf[2] = 0x43;
                        buf[3] = 0; // ping packet number
                        buf[4] = (byte)(Oneline.Index >> 8);
                        buf[5] = (byte)(Oneline.Index & 0xff);
                        // Multics Identification
                        buf[6] = (byte)ID; // unused must be zero (for next use)
                        buf[7] = (byte)('M' ^ buf[1] ^ buf[2] ^ buf[3] ^ buf[4] ^ buf[5] ^ buf[6]); // Multics Checksum
                        buf[8] = (byte)'M'; // Multics ID
                                            //Port
                        buf[9] = 0;
                        buf[10] = 0;
                        buf[11] = (byte)((int)CachePort.Value >> 8);
                        buf[12] = (byte)((int)CachePort.Value & 0xff);
                        //Program
                        buf[13] = 0x01; //ID
                        buf[14] = 7; //LEN
                        buf[15] = (byte)'M';
                        buf[16] = (byte)'u';
                        buf[17] = (byte)'l';
                        buf[18] = (byte)'t';
                        buf[19] = (byte)'i';
                        buf[20] = (byte)'C';
                        buf[21] = (byte)'S';
                        //Version
                        buf[22] = 0x02; //ID
                                        //	if (REVISION<100) {
                        buf[23] = 3; //LEN
                        buf[24] = (byte)'r';
                        int REVISION = 81;
                        buf[25] = (byte)('0' + (REVISION / 10));
                        buf[26] = (byte)('0' + (REVISION % 10));



                        MainCSP CSPPeer = new MainCSP
                        {
                            //CachePort = (int)CachePort.Value,
                            MSec = Oneline.Index,
                            CachePeer = CachePeer
                        };
                        PeerList.Add(CSPPeer);

                        serverSocket.BeginSendTo(buf, 0, buf.Length, SocketFlags.None, epSender, new AsyncCallback(OnSend), null);
                        sendDone.WaitOne();
                    }
                    catch (Exception ex)
                    {
                        MessageBox.Show(ex.Message, "SGSServerUDP1",
                            MessageBoxButtons.OK, MessageBoxIcon.Error);
                    }

                }

            });
            task.Start();

            WatchTest.Stop();
            ShowWatch.Stop();
            StopwatchBut.Text = string.Format("{0}D {1}h : {2}m : {3}.{4}s", WatchTest.Elapsed.Days, WatchTest.Elapsed.Hours, WatchTest.Elapsed.Minutes, WatchTest.Elapsed.Seconds, WatchTest.Elapsed.Milliseconds);
            Form1.IsVoice = SpeakerSwitch.Value;
            VoiceButtonItem.PerformClick();
            DesktopAlert.Show();
            DesktopAlert.CaptionText = string.Format("Lines Tester (ID:{0})", Form1.SessionID);
            DesktopAlert.ContentText = string.Format("The test is completed." + Environment.NewLine + "||Working({0})||Syntax({1})||Other({2})||", WorkBtn.Counter.Text, SyntaxBtn.Counter.Text, OtherBtn.Counter.Text);
            ltlStartButton.Enabled = true;
        }

        public void OnSend(IAsyncResult ar)
        {

            try
            {

                serverSocket.EndSend(ar);
                sendDone.Set();

            }
            catch (Exception ex)
            {
                MessageBox.Show(ex.Message, "SGSServerUDP2", MessageBoxButtons.OK, MessageBoxIcon.Error);
            }
        }

收到的代码:

        void Receive()
        {

            try
            {
                CheckForIllegalCrossThreadCalls = false;

                //We are using UDP sockets
                serverSocket = new Socket(AddressFamily.InterNetwork,
                    SocketType.Dgram, ProtocolType.Udp);

                //Assign the any IP of the machine and listen on port number 1000
                IPEndPoint ipEndPoint = new IPEndPoint(IPAddress.Any, (int)CachePort.Value);

                //Bind this address to the server
                serverSocket.Bind(ipEndPoint);

                IPEndPoint ipeSender = new IPEndPoint(IPAddress.Any, 0);
                //The epSender identifies the incoming clients
                EndPoint epSender = (EndPoint)ipeSender;

                //Start receiving data
                serverSocket.BeginReceiveFrom(byteData, 0, byteData.Length,
                    SocketFlags.None, ref epSender, new AsyncCallback(OnReceive), epSender);
            }
            catch (Exception ex)
            {
                MessageBox.Show(ex.Message, "SGSServerUDP3",
                    MessageBoxButtons.OK, MessageBoxIcon.Error);
            }
        }

        private void OnReceive(IAsyncResult ar)
        {
            try
            {
                IPEndPoint ipeSender = new IPEndPoint(IPAddress.Any, 0);
                EndPoint epSender = (EndPoint)ipeSender;

                serverSocket.EndReceiveFrom(ar, ref epSender);

                const int TYPE_PINGRPL = 4;
                switch (byteData[0])
                {
                    case TYPE_PINGRPL:
                        int result = PeerList.FindIndex(x => x.MSec == ((byteData[4] << 8) | byteData[5]));
                        if (result != -1)
                        {
                            WorkBtn.AddData(PeerList[result].CachePeer + "(" + ((byteData[4] << 8) | byteData[5]) + ")" + Environment.NewLine);
                            DesktopAlert.ContentText = string.Format("The test is completed." + Environment.NewLine + "||Working({0})||Syntax({1})||Other({2})||", WorkBtn.Counter.Text, SyntaxBtn.Counter.Text, OtherBtn.Counter.Text);
                            PeerList.RemoveAt(result);
                        }
                        break;
                }
                serverSocket.BeginReceiveFrom(byteData, 0, byteData.Length, SocketFlags.None, ref epSender, new AsyncCallback(OnReceive), epSender);
            }
            catch (Exception ex)
            {
                MessageBox.Show(ex.Message, "SGSServerUDP4", MessageBoxButtons.OK, MessageBoxIcon.Error);
            }
        }

谢谢你




推荐答案

你必须实施你的"丢包检测和重发"如果您选择使用UDP,则需要机制。

You have to implement your "packet loss detection and resend" machnism if you choose to use UDP.

如果您希望自动为您处理此部分,请改用TCP。 (但是在这种情况下,你需要处理连接丢失 - 重新连接的情况)

If you want this part handled for you automatically, use TCP instead. (However in that case you'll need to handle connection lost-reconnection scenario)

======

我要创建一个TryParsePacket()函数在发现数据被破坏时抛出异常,然后发送数据包要求远程端在数据包中重新发送此序列号。

I'd create a TryParsePacket() function to throw exception when the data is found to be corrupted, and then send a packet to ask remote side to resend this sequence number in packet.

并且远程端需要缓存发送的数据包一段时间,在某些循环缓冲区中是可取的。当收到重发请求时,它应该发送丢失的数据包,或者只重新发送序列号大于请求的
序列号的每个数据包。

And the remote side need to cache the sent packets for some time, preferrable in some circular buffer. When received resend request it should either send the lost packet or just resend every packet with sequence number larger than the requested sequence number.

根据您选择的方法,本地方可能需要缓存收到的所有数据包并按顺序对它们进行排序。

Depending on the method you choose, the local side may need to cache any packets received and sort them into order.

有很多工作要做,如果没有你的消息说明,他们就无法完成它们(如果你想要"通用"方式,你应该切换回TCP / IP,传输层为你处理它,而不是重新发明
轮子。

There's a lot of work to do, and they cannot be done by others without specification of your messages (if you want the "generic" way, you should just switch back to TCP/IP, where the transportation layer handle it for you, instead of reinventing the wheel).


这篇关于使用udp C#发送和接收数据时丢失一些数据的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆