C# UDP通信 大数据情况下丢包

时间:2022-08-27 23:35:10
用SOCKET UDP通信写了个程序 但是在数据量很大的时候(信息收发速度加快、信息量大时)会出现丢包的情况,请大神帮忙看看程序
Socket udpServer;
IPEndPoint serverIP=new IPEndPoint(IPAddress.Parse(xxx.xx.x.xxx),9199);
udpServer.Bind(serverIP);
EndPoint.Remote=(EndPoint)serverIP

new Thread(()=>
   {
       while(true)
        {
               byte[] data=new byte[102400];
               try
                 {
                   length=udpServer.ReceiveFrom(data, ref Remote);
                     if(length<=0)
                     break;

                   string str1=Encoding.GetEncoding("GBK").GetString(data,0,length);

                    Invoke(new ThreadStart(delegate()
                       {
                        this.textBox1.ApprendText(str1+Environment.NewLine);
                        this.textBox1.ScollToCaret();
                       }))
               }
             catch(Exception e)
              {
                MessageBox.Show(e.Message);
               }

        }
 
}).Start();
将收到的str1逐行添加到textbox1时,会出现丢包 

18 个解决方案

#1


udp本来就是不可靠通讯。

你知道有个tcp么?

tcp才是可靠的通讯(之一)。

#2


“看程序”没有多大意义,因为连基本的教科书上的概念都保证说“udp丢包是非常正常、非常普遍的”。你可以多看两小本通讯方面的入门书即可有所收获。

#3


UDP本来就是允许丢包的,所以一般运用在视频中~就是卡一下,画面模糊一下也没有关系~
不允许丢包的场景 请用TCP

#4


各位大神们都发言了,,偶也来围观。。。。

#5


引用 1 楼 sp1234 的回复:
udp本来就是不可靠通讯。

你知道有个tcp么?

tcp才是可靠的通讯(之一)。


我是在本机上进行通信,我当然知道TCP

#6


UDP是在大量传输数据的时候允许丢包,一般用在视频上。
TCP有握手协议,所以不会丢包,很可靠,但是效率稍微有点低。

#7


引用 1 楼 sp1234 的回复:
udp本来就是不可靠通讯。

你知道有个tcp么?

tcp才是可靠的通讯(之一)。

单向传输必须用UPD,因为很多工业现场直接物理隔离了双向传输

#8


LZ可以改异步试试,比多线程效率高


static DataTable dt;
        static DataTable Abbdt;
        static SqlHelper objhelper;
        static SqlConnection conn;
        static OtherClass oc;
        // Attributes
        private ArrayList m_aryClients = new ArrayList(); // List of Client Connections
        public const string GaoxinUDPProtocol = @"FDFDV\d.\d{2}.\d{2}L\d{3}DT(2\d\d\d[-](0[1-9]|1[012])[-](0[1-9]|[12][0-9]|3[01])\s+\d{2}:\d{2}:\d{2}),(.*)FEFE";
        public const string GaoxinUDPData = @"^[0-9]*:[-+]?[0-9]*\.?[0-9]+([eE][-+]?[0-9]+)?:[0-9]*$";
        public const char Comma = ',';
        public const char Colon = ':';

        static Regex reg;
        static Regex dataReg;

        /// <summary>
        /// Application starts here. Create an instance of this class and use it
        /// as the main object.
        /// </summary>
        /// <param name="args"></param>
        static void Main(string[] args)
        {
            objhelper = new SqlHelper();
            conn = objhelper.getConn();
            conn.Open();
            oc = new OtherClass();

            reg = new Regex(GaoxinUDPProtocol);
            dataReg = new Regex(GaoxinUDPData);

            int nPortListen = oc.lPort();

            IPAddress ip = IPAddress.Parse(oc.IPAddress());
            IPAddress ipAny = IPAddress.Any;
            IPEndPoint ipe = new IPEndPoint(ip, nPortListen);

            m_sListen = new Socket(AddressFamily.InterNetwork, SocketType.Dgram, ProtocolType.Udp);
            m_sListen.Bind(ipe);

            //IPEndPoint sender = new IPEndPoint(IPAddress.Any, 0);
            //EndPoint remote = (EndPoint)sender;


            EndPoint remote = (EndPoint)ipe;

            PostRecv(ipe);
            Console.WriteLine("请按回车键结束!");

            Console.ReadKey();

            conn.Close();


            GC.Collect();
            GC.WaitForPendingFinalizers();
        }


        #region UDP

        static Socket m_sListen;
        private static void ListenThreadMothed()
        {


        }

        private static void PostRecv(EndPoint endPoint)
        {
            byte[] buffer = new byte[1048576];
            m_sListen.BeginReceiveFrom(buffer, 0, buffer.Length, SocketFlags.None, ref endPoint, EndRecv, new AsyncState(buffer, 0, buffer.Length, endPoint));
        }

        private static void PostSend(byte[] buffer, int offset, int size, EndPoint endPoint)
        {
            m_sListen.BeginSendTo(buffer,
                offset,
                size,
                SocketFlags.None,
                endPoint,
                EndSend,
                new AsyncState(buffer, offset, size, endPoint));
        }

        private static void EndRecv(IAsyncResult asyncResult)
        {
            AsyncState state = (AsyncState)asyncResult.AsyncState;
            try
            {


                m_sListen.EndReceiveFrom(asyncResult, ref state.EndPoint);
                if (state.Buffer.Length > 20)
                {
                    string recString = System.Text.Encoding.Default.GetString(state.Buffer);
                    string[] UDPItems;
                    string[] UDPItem0;
                    string strSetp = "0", strInp = "0", strOutp = "0", strFeedBack = "0", strTotal_E = "0", strA_Current = "0", strAB_Voltage = "0", strA_Current2 = "0", strAB_Voltage2 = "0", No1M_Run = "0", No2M_Run = "0";
                    Match mat = reg.Match(recString.Trim(), 0);
                    //recString.IndexOf(',');
                    //recString.IndexOf(':');
                    if (mat.Success)
                    {
                        UDPItems = mat.Groups[4].Value.Split(Comma);
                        string[] udpItemFor;

                       
                        UDPItem0 = UDPItems[0].Split(Colon);
                        int intNO = int.Parse(UDPItem0[0]);
                        foreach (var item in UDPItems)
                        {
                            udpItemFor = item.Split(Colon);
                            int strNO = int.Parse(udpItemFor[0]);
                            if (strNO - intNO >= 80)
                            {
                                break;
                            }
                            int theV = strNO % 80;
                            switch (theV)
                            {
                                case 0: strSetp = udpItemFor[1];
                                    break;
                                case 1: strInp = udpItemFor[1];
                                    break;
                                case 2: strOutp = udpItemFor[1];
                                    break;
                                case 4: strFeedBack = udpItemFor[1];
                                    break;
                                case 37: strTotal_E = udpItemFor[1];
                                    break;
                                case 5: strA_Current = udpItemFor[1];
                                    break;
                                case 17: strAB_Voltage = udpItemFor[1];
                                    break;
                                case 8: strA_Current2 = udpItemFor[1];
                                    break;
                                case 20: strAB_Voltage2 = udpItemFor[1];
                                    break;
                                case 42: No1M_Run = udpItemFor[1];
                                    break;
                                case 45: No2M_Run = udpItemFor[1];
                                    break;
                            }
                        }
                        //UDPItem1 = UDPItems[1].Split(Colon);
                        //UDPItem2 = UDPItems[2].Split(Colon);
                        //UDPItemFeedBack = UDPItems[3].Split(Colon);
                        //UDPItemTotal_E = UDPItems[8].Split(Colon);
                        //UDPItemA_Current = UDPItems[4].Split(Colon);
                        //UDPItemAB_Voltage = UDPItems[6].Split(Colon);
                        if (UDPItem0.Length > 0)
                        {
                            //string valueStr = "设压:" + strSetp + "|进压:" + strInp + "|出压:" + strOutp;
                            //string recstring2 = recString.Substring(recString.IndexOf(',') + 1);
                            Console.WriteLine("No:" + UDPItem0[0] + "设压:" + strSetp + "|进压:" + strInp + "|出压:" + strOutp + "|OPC时间:" + mat.Groups[1] + ":");
                            //string recString3 = recstring2.Substring(0, recstring2.IndexOf(':'));
                            objhelper.UpdateSql(conn, UDPItem0[0], strSetp, strInp, strOutp, mat.Groups[1].ToString(), strFeedBack, strTotal_E, strA_Current, strAB_Voltage, strA_Current2, strAB_Voltage2, No1M_Run, No2M_Run);
                        }
                    }

                }

                PostRecv(state.EndPoint);
            }
            catch (Exception ex)
            {
                Console.WriteLine(ex.Message);

                PostRecv(state.EndPoint);
            }

            //  PostSend(state.Buffer, state.Offset, state.Size, state.EndPoint);
        }

        private static void EndSend(IAsyncResult asyncResult)
        {
            AsyncState state = (AsyncState)asyncResult.AsyncState;
            byte[] buffer = state.Buffer;
            int sendBytes = m_sListen.EndSendTo(asyncResult);
            int remainBytes = state.Size - sendBytes;
            if (remainBytes <= 0)
                return;
            PostSend(buffer, buffer.Length - remainBytes, remainBytes, state.EndPoint);
        }

        [Serializable, StructLayout(LayoutKind.Sequential)]
        internal struct AsyncState
        {
            private readonly byte[] buffer;
            private readonly int offset;
            private readonly int size;

            public AsyncState(byte[] buffer, EndPoint endPoint)
            {
                if (endPoint == null)
                {
                    throw new ArgumentNullException("endPoint");
                }
                this.buffer = buffer;
                this.offset = 0;
                this.size = buffer.Length;
                this.EndPoint = endPoint;
            }

            public AsyncState(byte[] buffer, int offset, int size, EndPoint endPoint)
            {
                if (buffer == null)
                {
                    throw new ArgumentNullException("array");
                }
                if (offset < 0)
                {
                    throw new ArgumentOutOfRangeException("offset", "ArgumentOutOfRange_NeedNonNegNum");
                }
                if (size < 0)
                {
                    throw new ArgumentOutOfRangeException("count", "ArgumentOutOfRange_NeedNonNegNum");
                }
                if ((buffer.Length - offset) < size)
                {
                    throw new ArgumentException("Argument_InvalidOffLen");
                }
                if (endPoint == null)
                {
                    throw new ArgumentNullException("endPoint");
                }
                this.buffer = buffer;
                this.offset = offset;
                this.size = size;
                this.EndPoint = endPoint;
            }

            public byte[] Buffer
            {
                get { return buffer; }
            }

            public int Offset
            {
                get { return offset; }
            }

            public int Size
            {
                get { return size; }
            }

            public EndPoint EndPoint;

        }


这是我写的一个UPDserver接受你可以参考参考,数据量不小

#9


感觉使用UDP丢包很难避免啊

#10


换个协议吧。
试试rtp

#11


谢谢你的代码,但是有点看不懂啊

#12


UDP是不可靠的传输方式

#13


引用 12 楼 huiguimoyu 的回复:
UDP是不可靠的传输方式


我知道,但是这里必须用到UDP,如果用TCP我也就没这问题了

#15


允许丢包的场景才会UDP。比如游戏里面的走动。即使丢几个包。也不要紧。

#16


还有就知道为什么丢包。是发的数据量超过上行,接收超过了下行,3G,WIFI的时候是不是信息号不好。还是TTL太大。

#17


我自己做了个测试
让发送端一次性发送300条信息过来 我发现在接收的端口上只能收到几十个,而且我已经把对接收到的信息处理程序停掉,只是单纯的接收,想问下有没有方法能够增强端口接收大数据的能力啊

#18


兄弟,先不说UDP丢包情况,你还需要考虑的一个问题就是Socket接收缓冲区是否溢出。因为你用的是TextBox类增方式这个累计以后耗时还是有点长的。为什么一丢失信息就考虑丢包呢?就不考虑是否溢出?UDP与TCP比确实不可靠一些,但是在我测试这么久以来还是感觉挺稳定的。至少在局域网里面是的。

#1


udp本来就是不可靠通讯。

你知道有个tcp么?

tcp才是可靠的通讯(之一)。

#2


“看程序”没有多大意义,因为连基本的教科书上的概念都保证说“udp丢包是非常正常、非常普遍的”。你可以多看两小本通讯方面的入门书即可有所收获。

#3


UDP本来就是允许丢包的,所以一般运用在视频中~就是卡一下,画面模糊一下也没有关系~
不允许丢包的场景 请用TCP

#4


各位大神们都发言了,,偶也来围观。。。。

#5


引用 1 楼 sp1234 的回复:
udp本来就是不可靠通讯。

你知道有个tcp么?

tcp才是可靠的通讯(之一)。


我是在本机上进行通信,我当然知道TCP

#6


UDP是在大量传输数据的时候允许丢包,一般用在视频上。
TCP有握手协议,所以不会丢包,很可靠,但是效率稍微有点低。

#7


引用 1 楼 sp1234 的回复:
udp本来就是不可靠通讯。

你知道有个tcp么?

tcp才是可靠的通讯(之一)。

单向传输必须用UPD,因为很多工业现场直接物理隔离了双向传输

#8


LZ可以改异步试试,比多线程效率高


static DataTable dt;
        static DataTable Abbdt;
        static SqlHelper objhelper;
        static SqlConnection conn;
        static OtherClass oc;
        // Attributes
        private ArrayList m_aryClients = new ArrayList(); // List of Client Connections
        public const string GaoxinUDPProtocol = @"FDFDV\d.\d{2}.\d{2}L\d{3}DT(2\d\d\d[-](0[1-9]|1[012])[-](0[1-9]|[12][0-9]|3[01])\s+\d{2}:\d{2}:\d{2}),(.*)FEFE";
        public const string GaoxinUDPData = @"^[0-9]*:[-+]?[0-9]*\.?[0-9]+([eE][-+]?[0-9]+)?:[0-9]*$";
        public const char Comma = ',';
        public const char Colon = ':';

        static Regex reg;
        static Regex dataReg;

        /// <summary>
        /// Application starts here. Create an instance of this class and use it
        /// as the main object.
        /// </summary>
        /// <param name="args"></param>
        static void Main(string[] args)
        {
            objhelper = new SqlHelper();
            conn = objhelper.getConn();
            conn.Open();
            oc = new OtherClass();

            reg = new Regex(GaoxinUDPProtocol);
            dataReg = new Regex(GaoxinUDPData);

            int nPortListen = oc.lPort();

            IPAddress ip = IPAddress.Parse(oc.IPAddress());
            IPAddress ipAny = IPAddress.Any;
            IPEndPoint ipe = new IPEndPoint(ip, nPortListen);

            m_sListen = new Socket(AddressFamily.InterNetwork, SocketType.Dgram, ProtocolType.Udp);
            m_sListen.Bind(ipe);

            //IPEndPoint sender = new IPEndPoint(IPAddress.Any, 0);
            //EndPoint remote = (EndPoint)sender;


            EndPoint remote = (EndPoint)ipe;

            PostRecv(ipe);
            Console.WriteLine("请按回车键结束!");

            Console.ReadKey();

            conn.Close();


            GC.Collect();
            GC.WaitForPendingFinalizers();
        }


        #region UDP

        static Socket m_sListen;
        private static void ListenThreadMothed()
        {


        }

        private static void PostRecv(EndPoint endPoint)
        {
            byte[] buffer = new byte[1048576];
            m_sListen.BeginReceiveFrom(buffer, 0, buffer.Length, SocketFlags.None, ref endPoint, EndRecv, new AsyncState(buffer, 0, buffer.Length, endPoint));
        }

        private static void PostSend(byte[] buffer, int offset, int size, EndPoint endPoint)
        {
            m_sListen.BeginSendTo(buffer,
                offset,
                size,
                SocketFlags.None,
                endPoint,
                EndSend,
                new AsyncState(buffer, offset, size, endPoint));
        }

        private static void EndRecv(IAsyncResult asyncResult)
        {
            AsyncState state = (AsyncState)asyncResult.AsyncState;
            try
            {


                m_sListen.EndReceiveFrom(asyncResult, ref state.EndPoint);
                if (state.Buffer.Length > 20)
                {
                    string recString = System.Text.Encoding.Default.GetString(state.Buffer);
                    string[] UDPItems;
                    string[] UDPItem0;
                    string strSetp = "0", strInp = "0", strOutp = "0", strFeedBack = "0", strTotal_E = "0", strA_Current = "0", strAB_Voltage = "0", strA_Current2 = "0", strAB_Voltage2 = "0", No1M_Run = "0", No2M_Run = "0";
                    Match mat = reg.Match(recString.Trim(), 0);
                    //recString.IndexOf(',');
                    //recString.IndexOf(':');
                    if (mat.Success)
                    {
                        UDPItems = mat.Groups[4].Value.Split(Comma);
                        string[] udpItemFor;

                       
                        UDPItem0 = UDPItems[0].Split(Colon);
                        int intNO = int.Parse(UDPItem0[0]);
                        foreach (var item in UDPItems)
                        {
                            udpItemFor = item.Split(Colon);
                            int strNO = int.Parse(udpItemFor[0]);
                            if (strNO - intNO >= 80)
                            {
                                break;
                            }
                            int theV = strNO % 80;
                            switch (theV)
                            {
                                case 0: strSetp = udpItemFor[1];
                                    break;
                                case 1: strInp = udpItemFor[1];
                                    break;
                                case 2: strOutp = udpItemFor[1];
                                    break;
                                case 4: strFeedBack = udpItemFor[1];
                                    break;
                                case 37: strTotal_E = udpItemFor[1];
                                    break;
                                case 5: strA_Current = udpItemFor[1];
                                    break;
                                case 17: strAB_Voltage = udpItemFor[1];
                                    break;
                                case 8: strA_Current2 = udpItemFor[1];
                                    break;
                                case 20: strAB_Voltage2 = udpItemFor[1];
                                    break;
                                case 42: No1M_Run = udpItemFor[1];
                                    break;
                                case 45: No2M_Run = udpItemFor[1];
                                    break;
                            }
                        }
                        //UDPItem1 = UDPItems[1].Split(Colon);
                        //UDPItem2 = UDPItems[2].Split(Colon);
                        //UDPItemFeedBack = UDPItems[3].Split(Colon);
                        //UDPItemTotal_E = UDPItems[8].Split(Colon);
                        //UDPItemA_Current = UDPItems[4].Split(Colon);
                        //UDPItemAB_Voltage = UDPItems[6].Split(Colon);
                        if (UDPItem0.Length > 0)
                        {
                            //string valueStr = "设压:" + strSetp + "|进压:" + strInp + "|出压:" + strOutp;
                            //string recstring2 = recString.Substring(recString.IndexOf(',') + 1);
                            Console.WriteLine("No:" + UDPItem0[0] + "设压:" + strSetp + "|进压:" + strInp + "|出压:" + strOutp + "|OPC时间:" + mat.Groups[1] + ":");
                            //string recString3 = recstring2.Substring(0, recstring2.IndexOf(':'));
                            objhelper.UpdateSql(conn, UDPItem0[0], strSetp, strInp, strOutp, mat.Groups[1].ToString(), strFeedBack, strTotal_E, strA_Current, strAB_Voltage, strA_Current2, strAB_Voltage2, No1M_Run, No2M_Run);
                        }
                    }

                }

                PostRecv(state.EndPoint);
            }
            catch (Exception ex)
            {
                Console.WriteLine(ex.Message);

                PostRecv(state.EndPoint);
            }

            //  PostSend(state.Buffer, state.Offset, state.Size, state.EndPoint);
        }

        private static void EndSend(IAsyncResult asyncResult)
        {
            AsyncState state = (AsyncState)asyncResult.AsyncState;
            byte[] buffer = state.Buffer;
            int sendBytes = m_sListen.EndSendTo(asyncResult);
            int remainBytes = state.Size - sendBytes;
            if (remainBytes <= 0)
                return;
            PostSend(buffer, buffer.Length - remainBytes, remainBytes, state.EndPoint);
        }

        [Serializable, StructLayout(LayoutKind.Sequential)]
        internal struct AsyncState
        {
            private readonly byte[] buffer;
            private readonly int offset;
            private readonly int size;

            public AsyncState(byte[] buffer, EndPoint endPoint)
            {
                if (endPoint == null)
                {
                    throw new ArgumentNullException("endPoint");
                }
                this.buffer = buffer;
                this.offset = 0;
                this.size = buffer.Length;
                this.EndPoint = endPoint;
            }

            public AsyncState(byte[] buffer, int offset, int size, EndPoint endPoint)
            {
                if (buffer == null)
                {
                    throw new ArgumentNullException("array");
                }
                if (offset < 0)
                {
                    throw new ArgumentOutOfRangeException("offset", "ArgumentOutOfRange_NeedNonNegNum");
                }
                if (size < 0)
                {
                    throw new ArgumentOutOfRangeException("count", "ArgumentOutOfRange_NeedNonNegNum");
                }
                if ((buffer.Length - offset) < size)
                {
                    throw new ArgumentException("Argument_InvalidOffLen");
                }
                if (endPoint == null)
                {
                    throw new ArgumentNullException("endPoint");
                }
                this.buffer = buffer;
                this.offset = offset;
                this.size = size;
                this.EndPoint = endPoint;
            }

            public byte[] Buffer
            {
                get { return buffer; }
            }

            public int Offset
            {
                get { return offset; }
            }

            public int Size
            {
                get { return size; }
            }

            public EndPoint EndPoint;

        }


这是我写的一个UPDserver接受你可以参考参考,数据量不小

#9


感觉使用UDP丢包很难避免啊

#10


换个协议吧。
试试rtp

#11


谢谢你的代码,但是有点看不懂啊

#12


UDP是不可靠的传输方式

#13


引用 12 楼 huiguimoyu 的回复:
UDP是不可靠的传输方式


我知道,但是这里必须用到UDP,如果用TCP我也就没这问题了

#14


#15


允许丢包的场景才会UDP。比如游戏里面的走动。即使丢几个包。也不要紧。

#16


还有就知道为什么丢包。是发的数据量超过上行,接收超过了下行,3G,WIFI的时候是不是信息号不好。还是TTL太大。

#17


我自己做了个测试
让发送端一次性发送300条信息过来 我发现在接收的端口上只能收到几十个,而且我已经把对接收到的信息处理程序停掉,只是单纯的接收,想问下有没有方法能够增强端口接收大数据的能力啊

#18


兄弟,先不说UDP丢包情况,你还需要考虑的一个问题就是Socket接收缓冲区是否溢出。因为你用的是TextBox类增方式这个累计以后耗时还是有点长的。为什么一丢失信息就考虑丢包呢?就不考虑是否溢出?UDP与TCP比确实不可靠一些,但是在我测试这么久以来还是感觉挺稳定的。至少在局域网里面是的。