Socket之UDP分包组包
2014-06-11 13:48 xchit 阅读(6036) 评论(0) 编辑 收藏 举报一般传输大的文件和信息的时候需要涉及到分包和组包,方法有很多,下面一种是借鉴了别人的思路,供大家参考哈
分包
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); //复制数据