Socket之UDP分包組包


   一般傳輸大的文件和信息的時候需要涉及到分包和組包,方法有很多,下面一種是借鑒了別人的思路,供大家參考哈

分包

  1、取出需要傳輸的文件和字符的長度和大小放入緩存區里面;

  2、設定固定傳輸的長度,用需要傳輸的長度除以固定傳輸的長度都可以得到需要傳輸的次數;

  3、傳輸一次字節流中包括(文件名字、文件名字大小、順序、數據總塊數、數據長度、數據總長度)

  4、包組裝完成后,都剩下發送;當確定到接收方收到后,在傳下一次包;

FileStream m = new FileStream(FullName, FileMode.Open, FileAccess.Read); //FullName得到文件完整路徑
                Byte[] BTmp = new byte[m.Length];
                m.Read(BTmp, 0, Convert.ToInt32(m.Length));
                m.Close();
                string fileName = dirs[j].FullName.Replace("\\", "/");
                while (fileName.IndexOf("/") > -1)
                {
                    fileName = fileName.Substring(fileName.IndexOf("/") + 1);
                }
                byte[] fileNameByte = Encoding.UTF8.GetBytes(fileName);
                byte[] fileNameLen = BitConverter.GetBytes(fileNameByte.Length);

                int m_intMessageLength = BTmp.Length;
                int m_intSerial = 0;
                int m_intBlocks = Convert.ToInt32(Math.Ceiling(Convert.ToDouble(m_intMessageLength) / Convert.ToDouble(m_intBlockLength))); //數據分割塊數   
                int m_intlastlength = 0;
                //求出最后一塊數據長度
                if (m_intMessageLength % m_intBlockLength == 0)
                    m_intlastlength = m_intBlockLength;
                else
                    m_intlastlength = m_intMessageLength - (m_intBlocks - 1) * m_intBlockLength;

                while (m_intSerial < m_intBlocks)
                {
                    try
                    {
                        int m_intLength = 0; //數據長度   
                        if ((m_intSerial + 1) == m_intBlocks)
                            m_intLength = m_intlastlength;
                        else
                            m_intLength = m_intBlockLength;

                        byte[] data = new byte[m_intLength + 20 + fileNameByte.Length];
                        int place = 0;
                        Buffer.BlockCopy(BitConverter.GetBytes(m_intSerial), 0, data, place, 4); //順序戳   
                        place += 4;
                        Buffer.BlockCopy(BitConverter.GetBytes(m_intBlocks), 0, data, place, 4); //數據總塊數    
                        place += 4;
                        Buffer.BlockCopy(BitConverter.GetBytes(m_intLength), 0, data, place, 4); //數據長度   
                        place += 4;
                        Buffer.BlockCopy(BitConverter.GetBytes(BTmp.Length), 0, data, place, 4); //數據總長度   
                        place += 4;
                        ////////////////
                        Buffer.BlockCopy(fileNameLen, 0, data, place, 4); //文件名長度   
                        place += 4;
                        Buffer.BlockCopy(fileNameByte, 0, data, place, fileNameByte.Length); //文件名大小   
                        place += fileNameByte.Length;
                        Array.Copy(BTmp, m_intSerial * 1000, data, place, m_intLength); //復制數據 
                        sersoc.SendTo(data, 0, data.Length, SocketFlags.None, Remot);
                        bool result = sersoc.Poll(1000000, SelectMode.SelectRead);
                        if (result)
                        {
                            byte[] linshi = new byte[1024];
                            int recv = sersoc.ReceiveFrom(linshi, ref Remot);
                            int biaoji = BitConverter.ToInt32(linshi, 0);
                            int i = BitConverter.ToInt32(linshi, 4);//i值為111時表示接到客戶端的確認
                            if (biaoji == 999) m_intSerial = i;
                            if (i == 0) break;
                        }

                    } //endtry    
                    catch (System.Exception pe)
                    {
                        Console.WriteLine(pe.ToString());
                    }

組包

  1、收到包后,取出數據總長度和文件名字;

  2、根據順序寫入字節流中,還原成原始包;

 int m_intSerial = 0;
                int m_intBlocks = 0; //數據分割塊數   
                int m_intLength = 0; //數據長度   
                int m_intMessageLength = 0;
                int place = 0;
                int recv;
                int biaoji = 999;
                place = 0;
                m_intSerial = BitConverter.ToInt32(bytesF, place);//順序戳
                place += 4;
                m_intBlocks = BitConverter.ToInt32(bytesF, place);//數據總塊數
                place += 4;
                m_intLength = BitConverter.ToInt32(bytesF, place);//數據長度
                place += 4;
                m_intMessageLength = BitConverter.ToInt32(bytesF, place);//數據總長度
                place += 4;
                int count = BitConverter.ToInt32(bytesF, place);//文件名長度
                place += 4;
                string fileName = Encoding.UTF8.GetString(bytesF, place, count);//文件名
                place += count;
                if (m_intSerial == 0)
                { m_intGetCount = 0; data = new byte[m_intMessageLength];  } //申明數據的總長   

                Array.Copy(bytesF, place, data, m_intBlockLength * m_intSerial, m_intLength); //復制數據  

 


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM