zoukankan      html  css  js  c++  java
  • 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); //复制数据  
    
  • 相关阅读:
    基于WebDriverAgent代理服务,实现iOS手机app自动化测试的框架搭建
    ruby 中%Q %q %W %w %x %r %s的用法
    ruby中 Win32ole的各应用操作方法(word excel Outlook IE)
    dubbo服务自动化测试搭建
    Spring AOP 结合自定义注解的使用
    Mysql 中 JSON_CONTAINS、JSON_ARRAY 的使用
    Spring Cloud Eureka 的一些配置
    Spring Cloud 整合 Spring Boot Admin
    Nginx 泛域名解析配置
    Spring Data Solr
  • 原文地址:https://www.cnblogs.com/xchit/p/3781788.html
Copyright © 2011-2022 走看看