public SuperUdpClient(UdpServer udpserver, EndPoint remoteendpoint)
        {
            Queuedreliabledata = new Queue <byte[]>();
            mudpclient         = new UdpClient(udpserver, remoteendpoint);
            mudpclient.OnReceivedCompletePointer = (ref byte[] buffer) => {
                if (isvalidedata(ref buffer))
                {
                    //int datasize = buffer.Length;
                    int  headersize      = header.Count;
                    byte un_reliablebyte = buffer[headersize];
                    if (un_reliablebyte == UNRELIABLESIGN)
                    {
                        byte normal_ackbyte = buffer[headersize + 1];
                        if (normal_ackbyte == NORMALDATASIGN)
                        {
                            int    commandsize = headersize + 1 + 1;
                            int    playloadsize;                                                       //= datasize - commandsize;
                            byte[] sizebyte = new byte[2];
                            Array.ConstrainedCopy(buffer, commandsize, sizebyte, 0, 2);                //here is 2 byte valide data length
                            playloadsize = ByteArraytoUint16.DeSerialize(ref sizebyte);                //here is 2 byte valide data length
                            realdata     = new byte[playloadsize];
                            Array.ConstrainedCopy(buffer, commandsize + 2, realdata, 0, playloadsize); //here is 2 byte valide data length

                            unreliabledatareceiveddelegate.Invoke(ref realdata);
                        }
                        else if (normal_ackbyte == ACKSIGN)
                        {
                            receiveackid = buffer[headersize + 2];
                            //Console.WriteLine("receiveackid"+ receiveackid);
                        }
                    }
                    else if (un_reliablebyte == RELIABLESIGN)
                    {
                        byte messageid = buffer[headersize + 1];
                        bool bspecial  = messageid == 0 && lastsendackid == 0xff;
                        if (bspecial || messageid > lastsendackid)
                        {
                            lastsendackid = messageid;
                            //+ reliable  + id
                            int    commandsize = headersize + 1 + +1;
                            int    playloadsize;                                                       //= datasize - commandsize;
                            byte[] sizebyte = new byte[2];
                            Array.ConstrainedCopy(buffer, commandsize, sizebyte, 0, 2);                //here is 2 byte valide data length
                            playloadsize = ByteArraytoUint16.DeSerialize(ref sizebyte);                //here is 2 byte valide data length
                            realdata     = new byte[playloadsize];
                            Array.ConstrainedCopy(buffer, commandsize + 2, realdata, 0, playloadsize); //here is 2 byte valide data length

                            reliabledatareceiveddelegate.Invoke(ref realdata);
                        }
                        sendack(messageid);
                    }
                }
            };
            Thread TransferListenerthread = new Thread(reliabletickwork);

            TransferListenerthread.IsBackground = true;
            TransferListenerthread.Start();
        }
        public void sendunreliable(ref byte[] buffer)
        {
            List <byte> tempcontent = new List <byte>();

            tempcontent.AddRange(header);
            tempcontent.Add(UNRELIABLESIGN); //mean unreliable
            tempcontent.Add(NORMALDATASIGN); //mean this is normal data
            int headersize = tempcontent.Count;

            byte[] temparray = new byte[headersize + 2 + buffer.Length];                                            // 2 mean 2 byte valide data length
            Array.ConstrainedCopy(tempcontent.ToArray(), 0, temparray, 0, headersize);                              //load header
            Array.ConstrainedCopy(ByteArraytoUint16.Serialize((UInt16)buffer.Length), 0, temparray, headersize, 2); // load 2 byte valide data length
            Array.ConstrainedCopy(buffer, 0, temparray, headersize + 2, buffer.Length);
            mudpclient.Send(temparray);
        }
        public void sendreliable(ref byte[] buffer)
        {
            List <byte> tempcontent = new List <byte>();

            tempcontent.AddRange(header);
            tempcontent.Add(RELIABLESIGN);     //mean reliable
            tempcontent.Add(reliabledataid++); //mean reliable message id
            int headersize = tempcontent.Count;

            byte[] temparray = new byte[headersize + 2 + buffer.Length];                                            // 2 mean 2 byte valide data length
            Array.ConstrainedCopy(tempcontent.ToArray(), 0, temparray, 0, headersize);                              //load header
            Array.ConstrainedCopy(ByteArraytoUint16.Serialize((UInt16)buffer.Length), 0, temparray, headersize, 2); // load 2 byte valide data length
            Array.ConstrainedCopy(buffer, 0, temparray, headersize + 2, buffer.Length);
            lock (QueuedreliabledataLock)
            {
                Queuedreliabledata.Enqueue(temparray);
            }
        }