一般传输大的文件和信息的时候需要涉及到分包和组包,方法有很多,下面一种是借鉴了别人的思路,供大家参考哈
分包
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); //复制数据
Socket之UDP分包组包