一般傳輸大的文件和信息的時候需要涉及到分包和組包,方法有很多,下面一種是借鑒了別人的思路,供大家參考哈
分包
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); //復制數據