基类
using
System;
using System.Collections.Generic;
using System.Text;
using System.IO;
namespace SocketServer
... {
public delegate void FileEvent(FileBase f);
public class FileBase
...{
protected FileStream _stream; //文件流
protected string _fileInfo; //文件说明,最长204字节
protected string _fileName; //文件名最长255字节
protected long _fileSize; //文件大小
protected int _allBagNums; //总包数
protected int _bagSize; //包大小
protected int _readLen; //实际每包可发送的有效字节
protected int _currentBag; //正在接收或发送的包数
protected byte[] _fileMark; //文件标识四字节,产生时为随机数
protected bool _checkout; //接收时是否进行检查
public const byte BagMark = 4; //包标识
public const int _firstBagLen = 8192;//第一包的长度
protected const int _checkLen = 16; //包尾检查位的长度
属性#region 属性
/**//// <summary>
/// 当前包
/// </summary>
public int CurrentBag
...{
get ...{ return _currentBag; }
//set { _currentBag = value; }
}
/**//// <summary>
/// 下一包
/// </summary>
public int NextBag
...{
get ...{ return _currentBag + 1; }
}
/**//// <summary>
/// 总包数
/// </summary>
public int AllBagNums
...{
get ...{ return _allBagNums; }
}
/**//// <summary>
/// 接收时是否进行检查
/// </summary>
public bool CheckOut
...{
get ...{ return _checkout; }
}
/**//// <summary>
/// 包大小
/// </summary>
public int BagSize
...{
get ...{ return _bagSize; }
}
#endregion
public FileBase()
...{
_fileInfo = "";
_fileMark = new byte[4];
_currentBag = -1;
_checkout = true;
}
~FileBase()
...{
if (_stream != null)
...{
_stream.Close();
}
_fileInfo = null;
_fileName = null;
}
public virtual void Close()
...{
if (_stream != null)
...{
_stream.Close();
}
}
/**//// <summary>
/// 得到每一包的前8个字节
/// 第一字节为包标识,后三字节为包序号.最后四个字节为文件标识
/// </summary>
/// <param name="bagNum">包序号</param>
/// <returns>byte[4]</returns>
protected byte[] getBagHead(int bagSequence)
...{
byte[] baghead = new byte[8];
baghead[0] = BagMark;
for (byte i = 1; i < 4; i++)
...{
baghead[i] = (byte)(bagSequence & 0xFF);
bagSequence = bagSequence >> 8;
}
Array.Copy(_fileMark, 0, baghead, 4, 4);
return baghead;
}
/**//// <summary>
/// 文件的附加信息(第一包)
/// </summary>
/// <returns>byte[]</returns>
protected byte[] GetBaseInfo()
...{
byte[] binBaghead = getBagHead(0);
byte[] binFileSize = Int2Bin(_fileSize, 8); //文件大小
byte[] binAllBagNums = Int2Bin(_allBagNums, 4); //总包数
byte[] binBagSize = Int2Bin(_bagSize, 4); //包大小
byte[] binReadLen = Int2Bin(_readLen, 4); //实际每包发送的有效字节
byte[] binFileName = Encoding.Default.GetBytes(_fileName); //文件名最长255字节
byte[] binFileInfo = Encoding.Default.GetBytes(_fileInfo); //文件说明,最长204字节
byte[] firstBag = new byte[_firstBagLen];
long desIndex = 0;
Array.Copy(binBaghead, 0, firstBag, desIndex, binBaghead.Length);
desIndex += binBaghead.Length;
Array.Copy(binFileSize, 0, firstBag, desIndex, 8);
desIndex += 8;
Array.Copy(binAllBagNums, 0, firstBag, desIndex, 4);
desIndex += 4;
Array.Copy(binBagSize, 0, firstBag, desIndex, 4);
desIndex += 4;
Array.Copy(binReadLen, 0, firstBag, desIndex, 4);
desIndex += 4;
Array.Copy(binFileName, 0, firstBag, desIndex, Math.Min(255, binFileName.Length));
desIndex += 255;
if (!_checkout) firstBag[desIndex] = 1; //是否启用检查,为1是不检查.其它则检查
desIndex += 1;
Array.Copy(binFileInfo, 0, firstBag, desIndex, Math.Min(196, binFileInfo.Length));
desIndex += 196;
return firstBag;
}
/**//// <summary>
/// 得到文件信息
/// </summary>
/// <param name="firstBag">第一包数据(包头加+附加信息,最少512字节)</param>
/// <returns>无错误,返回4(等于BagMark)</returns>
virtual protected int SetBaseInfo(byte[] firstBag)
...{
byte[] baghead = new byte[4];
byte[] binFileSize = new byte[8];
byte[] binAllBagNums = new byte[4];
byte[] binBagSize = new byte[4];
byte[] binReadLen = new byte[4];
byte[] binFileName = new byte[256];
byte[] binFileInfo = new byte[196];
long sourceIndex = 0;
Array.Copy(firstBag, sourceIndex, baghead, 0, 4);
sourceIndex += 4;
Array.Copy(firstBag, sourceIndex, _fileMark, 0, 4);
sourceIndex += 4;
Array.Copy(firstBag, sourceIndex, binFileSize, 0, 8);
sourceIndex += 8;
Array.Copy(firstBag, sourceIndex, binAllBagNums, 0, 4);
sourceIndex += 4;
Array.Copy(firstBag, sourceIndex, binBagSize, 0, 4);
sourceIndex += 4;
Array.Copy(firstBag, sourceIndex, binReadLen, 0, 4);
sourceIndex += 4;
Array.Copy(firstBag, sourceIndex, binFileName, 0, 255);
sourceIndex += 255;
if (firstBag[sourceIndex] == 1) ...{ _checkout = false; }
sourceIndex += 1;
Array.Copy(firstBag, sourceIndex, binFileInfo, 0, 196);
sourceIndex += 196;
_fileSize = Bin2Int(binFileSize);
_allBagNums = (int)Bin2Int(binAllBagNums);
_bagSize = (int)Bin2Int(binBagSize);
_readLen = (int)Bin2Int(binReadLen);
_fileName = Encoding.Default.GetString(binFileName).Trim('空');
_fileInfo = Encoding.Default.GetString(binFileInfo).Trim('空');
return ReadBagSequence(baghead) + firstBag[0];// +Bin2Int(_fileMark));
}
/**//// <summary>
/// 得到包序号
/// </summary>
/// <param name="baghead">包头(最少4字节)</param>
/// <returns>包序号</returns>
public static int ReadBagSequence(byte[] baghead)
...{
int bagSequence = 0;
for (byte i = 1; i < 4; i++)
...{
bagSequence += baghead[i] << ((i - 1) << 3);
}
return bagSequence;
}
/**//// <summary>
/// 将Int转换为Byte[4]
/// </summary>
public static byte[] Int2Bin(long intNum, int length)
...{
byte[] byteNew = new byte[length];
for (byte i = 0; i < length; i++)
...{
byteNew[i] = (byte)(intNum & 0xFF);
intNum = intNum >> 8;
}
return byteNew;
}
/**//// <summary>
/// 将byte转换为Int
/// </summary>
/// <param name="bin"></param>
/// <returns></returns>
public static long Bin2Int(byte[] bin)
...{
long values = 0;
for (byte i = 0; i < bin.Length; i++)
...{
values += ((long)bin[i]) << (i << 3);
}
return values;
}
}
}
using System.Collections.Generic;
using System.Text;
using System.IO;
namespace SocketServer
... {
public delegate void FileEvent(FileBase f);
public class FileBase
...{
protected FileStream _stream; //文件流
protected string _fileInfo; //文件说明,最长204字节
protected string _fileName; //文件名最长255字节
protected long _fileSize; //文件大小
protected int _allBagNums; //总包数
protected int _bagSize; //包大小
protected int _readLen; //实际每包可发送的有效字节
protected int _currentBag; //正在接收或发送的包数
protected byte[] _fileMark; //文件标识四字节,产生时为随机数
protected bool _checkout; //接收时是否进行检查
public const byte BagMark = 4; //包标识
public const int _firstBagLen = 8192;//第一包的长度
protected const int _checkLen = 16; //包尾检查位的长度
属性#region 属性
/**//// <summary>
/// 当前包
/// </summary>
public int CurrentBag
...{
get ...{ return _currentBag; }
//set { _currentBag = value; }
}
/**//// <summary>
/// 下一包
/// </summary>
public int NextBag
...{
get ...{ return _currentBag + 1; }
}
/**//// <summary>
/// 总包数
/// </summary>
public int AllBagNums
...{
get ...{ return _allBagNums; }
}
/**//// <summary>
/// 接收时是否进行检查
/// </summary>
public bool CheckOut
...{
get ...{ return _checkout; }
}
/**//// <summary>
/// 包大小
/// </summary>
public int BagSize
...{
get ...{ return _bagSize; }
}
#endregion
public FileBase()
...{
_fileInfo = "";
_fileMark = new byte[4];
_currentBag = -1;
_checkout = true;
}
~FileBase()
...{
if (_stream != null)
...{
_stream.Close();
}
_fileInfo = null;
_fileName = null;
}
public virtual void Close()
...{
if (_stream != null)
...{
_stream.Close();
}
}
/**//// <summary>
/// 得到每一包的前8个字节
/// 第一字节为包标识,后三字节为包序号.最后四个字节为文件标识
/// </summary>
/// <param name="bagNum">包序号</param>
/// <returns>byte[4]</returns>
protected byte[] getBagHead(int bagSequence)
...{
byte[] baghead = new byte[8];
baghead[0] = BagMark;
for (byte i = 1; i < 4; i++)
...{
baghead[i] = (byte)(bagSequence & 0xFF);
bagSequence = bagSequence >> 8;
}
Array.Copy(_fileMark, 0, baghead, 4, 4);
return baghead;
}
/**//// <summary>
/// 文件的附加信息(第一包)
/// </summary>
/// <returns>byte[]</returns>
protected byte[] GetBaseInfo()
...{
byte[] binBaghead = getBagHead(0);
byte[] binFileSize = Int2Bin(_fileSize, 8); //文件大小
byte[] binAllBagNums = Int2Bin(_allBagNums, 4); //总包数
byte[] binBagSize = Int2Bin(_bagSize, 4); //包大小
byte[] binReadLen = Int2Bin(_readLen, 4); //实际每包发送的有效字节
byte[] binFileName = Encoding.Default.GetBytes(_fileName); //文件名最长255字节
byte[] binFileInfo = Encoding.Default.GetBytes(_fileInfo); //文件说明,最长204字节
byte[] firstBag = new byte[_firstBagLen];
long desIndex = 0;
Array.Copy(binBaghead, 0, firstBag, desIndex, binBaghead.Length);
desIndex += binBaghead.Length;
Array.Copy(binFileSize, 0, firstBag, desIndex, 8);
desIndex += 8;
Array.Copy(binAllBagNums, 0, firstBag, desIndex, 4);
desIndex += 4;
Array.Copy(binBagSize, 0, firstBag, desIndex, 4);
desIndex += 4;
Array.Copy(binReadLen, 0, firstBag, desIndex, 4);
desIndex += 4;
Array.Copy(binFileName, 0, firstBag, desIndex, Math.Min(255, binFileName.Length));
desIndex += 255;
if (!_checkout) firstBag[desIndex] = 1; //是否启用检查,为1是不检查.其它则检查
desIndex += 1;
Array.Copy(binFileInfo, 0, firstBag, desIndex, Math.Min(196, binFileInfo.Length));
desIndex += 196;
return firstBag;
}
/**//// <summary>
/// 得到文件信息
/// </summary>
/// <param name="firstBag">第一包数据(包头加+附加信息,最少512字节)</param>
/// <returns>无错误,返回4(等于BagMark)</returns>
virtual protected int SetBaseInfo(byte[] firstBag)
...{
byte[] baghead = new byte[4];
byte[] binFileSize = new byte[8];
byte[] binAllBagNums = new byte[4];
byte[] binBagSize = new byte[4];
byte[] binReadLen = new byte[4];
byte[] binFileName = new byte[256];
byte[] binFileInfo = new byte[196];
long sourceIndex = 0;
Array.Copy(firstBag, sourceIndex, baghead, 0, 4);
sourceIndex += 4;
Array.Copy(firstBag, sourceIndex, _fileMark, 0, 4);
sourceIndex += 4;
Array.Copy(firstBag, sourceIndex, binFileSize, 0, 8);
sourceIndex += 8;
Array.Copy(firstBag, sourceIndex, binAllBagNums, 0, 4);
sourceIndex += 4;
Array.Copy(firstBag, sourceIndex, binBagSize, 0, 4);
sourceIndex += 4;
Array.Copy(firstBag, sourceIndex, binReadLen, 0, 4);
sourceIndex += 4;
Array.Copy(firstBag, sourceIndex, binFileName, 0, 255);
sourceIndex += 255;
if (firstBag[sourceIndex] == 1) ...{ _checkout = false; }
sourceIndex += 1;
Array.Copy(firstBag, sourceIndex, binFileInfo, 0, 196);
sourceIndex += 196;
_fileSize = Bin2Int(binFileSize);
_allBagNums = (int)Bin2Int(binAllBagNums);
_bagSize = (int)Bin2Int(binBagSize);
_readLen = (int)Bin2Int(binReadLen);
_fileName = Encoding.Default.GetString(binFileName).Trim('空');
_fileInfo = Encoding.Default.GetString(binFileInfo).Trim('空');
return ReadBagSequence(baghead) + firstBag[0];// +Bin2Int(_fileMark));
}
/**//// <summary>
/// 得到包序号
/// </summary>
/// <param name="baghead">包头(最少4字节)</param>
/// <returns>包序号</returns>
public static int ReadBagSequence(byte[] baghead)
...{
int bagSequence = 0;
for (byte i = 1; i < 4; i++)
...{
bagSequence += baghead[i] << ((i - 1) << 3);
}
return bagSequence;
}
/**//// <summary>
/// 将Int转换为Byte[4]
/// </summary>
public static byte[] Int2Bin(long intNum, int length)
...{
byte[] byteNew = new byte[length];
for (byte i = 0; i < length; i++)
...{
byteNew[i] = (byte)(intNum & 0xFF);
intNum = intNum >> 8;
}
return byteNew;
}
/**//// <summary>
/// 将byte转换为Int
/// </summary>
/// <param name="bin"></param>
/// <returns></returns>
public static long Bin2Int(byte[] bin)
...{
long values = 0;
for (byte i = 0; i < bin.Length; i++)
...{
values += ((long)bin[i]) << (i << 3);
}
return values;
}
}
}
发送文件类
using
System;
using System.Collections.Generic;
using System.Text;
using System.IO;
namespace SocketServer
... {
/**//// <summary>
/// 发送文件辅助类
/// </summary>
public class FileSend:FileBase
...{
构造函数#region 构造函数
public FileSend(int bagSize, bool checkout)
...{
bagSize = (bagSize >> 8) << 8; //256的整数倍
_bagSize = Math.Max(512, Math.Min(32768, bagSize));
Random rd = new Random();
_fileMark[0] = (byte)rd.Next(256);
_fileMark[1] = (byte)rd.Next(256);
_fileMark[2] = (byte)rd.Next(256);
_fileMark[3] = (byte)rd.Next(256);
_checkout = checkout;
//实际每包可发送的字节(8字节为包头,16字节为预留包尾)
if (_checkout)
...{
_readLen = _bagSize - (8 + 16);
}
else
...{
_readLen = _bagSize - 8;
}
}
public FileSend(int bagSize)
:this(bagSize,true)
...{
}
public FileSend(int bagSize, string filePath)
: this(bagSize,true)
...{
_stream = File.OpenRead(filePath);
_fileSize = _stream.Length;
_fileName = filePath.Substring(filePath.LastIndexOf('/') + 1);
_allBagNums = (int)Math.Ceiling(((double)_fileSize) / _readLen) + 1;
}
#endregion
/**//// <summary>
/// 读取包数据
/// </summary>
/// <returns></returns>
public byte[] Read()
...{
_currentBag++;
byte[] bag = new byte[_bagSize];
byte[] baghead = getBagHead(_currentBag);
Array.Copy(baghead, 0, bag, 0, 8);
if (_currentBag < _allBagNums)
...{
_stream.Read(bag, 8, _readLen);
return bag;
}
else
...{
_currentBag = -1;
return new byte[] ...{ };
}
}
/**//// <summary>
/// 读取文件信息
/// </summary>
/// <returns></returns>
public byte[] ReadBase()
...{
_currentBag = 0;
_stream.Position = 0;
return GetBaseInfo();
}
/**//// <summary>
/// 根据包序号读取包数据
/// </summary>
/// <param name="bagSequence">包序号(从第1包数据开始)</param>
/// <returns>byte[]</returns>
public byte[] GetBags(int bagSequence)
...{
byte[] bag = new byte[_bagSize];
byte[] baghead = getBagHead(bagSequence);
Array.Copy(baghead, 0, bag, 0, 8);
int readLen = 0;
if (bagSequence == 0)
...{
return ReadBase();
}
else if (bagSequence < _allBagNums)
...{
long position = (bagSequence - 1) * _readLen;
lock (_stream)
...{
long sp = _stream.Position;
if (_stream.Position != position)
...{
_stream.Position = position;
}
readLen = _stream.Read(bag, 8, _readLen);
_stream.Position = sp;
}
return bag;
}
return new byte[] ...{ };
}
}
}
using System.Collections.Generic;
using System.Text;
using System.IO;
namespace SocketServer
... {
/**//// <summary>
/// 发送文件辅助类
/// </summary>
public class FileSend:FileBase
...{
构造函数#region 构造函数
public FileSend(int bagSize, bool checkout)
...{
bagSize = (bagSize >> 8) << 8; //256的整数倍
_bagSize = Math.Max(512, Math.Min(32768, bagSize));
Random rd = new Random();
_fileMark[0] = (byte)rd.Next(256);
_fileMark[1] = (byte)rd.Next(256);
_fileMark[2] = (byte)rd.Next(256);
_fileMark[3] = (byte)rd.Next(256);
_checkout = checkout;
//实际每包可发送的字节(8字节为包头,16字节为预留包尾)
if (_checkout)
...{
_readLen = _bagSize - (8 + 16);
}
else
...{
_readLen = _bagSize - 8;
}
}
public FileSend(int bagSize)
:this(bagSize,true)
...{
}
public FileSend(int bagSize, string filePath)
: this(bagSize,true)
...{
_stream = File.OpenRead(filePath);
_fileSize = _stream.Length;
_fileName = filePath.Substring(filePath.LastIndexOf('/') + 1);
_allBagNums = (int)Math.Ceiling(((double)_fileSize) / _readLen) + 1;
}
#endregion
/**//// <summary>
/// 读取包数据
/// </summary>
/// <returns></returns>
public byte[] Read()
...{
_currentBag++;
byte[] bag = new byte[_bagSize];
byte[] baghead = getBagHead(_currentBag);
Array.Copy(baghead, 0, bag, 0, 8);
if (_currentBag < _allBagNums)
...{
_stream.Read(bag, 8, _readLen);
return bag;
}
else
...{
_currentBag = -1;
return new byte[] ...{ };
}
}
/**//// <summary>
/// 读取文件信息
/// </summary>
/// <returns></returns>
public byte[] ReadBase()
...{
_currentBag = 0;
_stream.Position = 0;
return GetBaseInfo();
}
/**//// <summary>
/// 根据包序号读取包数据
/// </summary>
/// <param name="bagSequence">包序号(从第1包数据开始)</param>
/// <returns>byte[]</returns>
public byte[] GetBags(int bagSequence)
...{
byte[] bag = new byte[_bagSize];
byte[] baghead = getBagHead(bagSequence);
Array.Copy(baghead, 0, bag, 0, 8);
int readLen = 0;
if (bagSequence == 0)
...{
return ReadBase();
}
else if (bagSequence < _allBagNums)
...{
long position = (bagSequence - 1) * _readLen;
lock (_stream)
...{
long sp = _stream.Position;
if (_stream.Position != position)
...{
_stream.Position = position;
}
readLen = _stream.Read(bag, 8, _readLen);
_stream.Position = sp;
}
return bag;
}
return new byte[] ...{ };
}
}
}
接收文件类
using
System;
using System.Collections.Generic;
using System.Text;
using System.IO;
namespace SocketServer
... {
public class FileRece : FileBase
...{
/**//// <summary>
/// 接收完文件事件
/// </summary>
public event FileEvent ReceivedFile;
string _filePath;
构造函数#region 构造函数
public FileRece(string fileDirectory)
...{
_filePath = fileDirectory.TrimEnd('/');
if (!Directory.Exists(fileDirectory))
...{
Directory.CreateDirectory(fileDirectory);
}
}
public FileRece()
: this(Environment.CurrentDirectory + @"Temp")
...{
}
#endregion
/**//// <summary>
/// 创建文件流
/// </summary>
private void creatFile()
...{
string fileFullPaht = _filePath + @"" + _fileName;
while (File.Exists(fileFullPaht))
...{
fileFullPaht += DateTime.Now.ToFileTime().ToString();
}
_stream = File.Create(fileFullPaht);
}
/**//// <summary>
/// 初始化
/// </summary>
/// <param name="firstBag">接收到的第一包数据</param>
/// <returns></returns>
public int Initialize(byte[] firstBag)
...{
int result = SetBaseInfo(firstBag);
creatFile();
_currentBag = 0;
return result;
}
/**//// <summary>
/// 写数据
/// </summary>
/// <param name="bin"></param>
public void Write(byte[] bin)
...{
_currentBag++;
long count = _fileSize -(_stream.Length + _readLen);
if (count > 0)
...{
_stream.Write(bin, 8, _readLen);
}
else
...{
_stream.Write(bin, 8, (int)(_readLen+count));
_stream.Close();
if (ReceivedFile != null) ReceivedFile(this);
}
}
}
}
using System.Collections.Generic;
using System.Text;
using System.IO;
namespace SocketServer
... {
public class FileRece : FileBase
...{
/**//// <summary>
/// 接收完文件事件
/// </summary>
public event FileEvent ReceivedFile;
string _filePath;
构造函数#region 构造函数
public FileRece(string fileDirectory)
...{
_filePath = fileDirectory.TrimEnd('/');
if (!Directory.Exists(fileDirectory))
...{
Directory.CreateDirectory(fileDirectory);
}
}
public FileRece()
: this(Environment.CurrentDirectory + @"Temp")
...{
}
#endregion
/**//// <summary>
/// 创建文件流
/// </summary>
private void creatFile()
...{
string fileFullPaht = _filePath + @"" + _fileName;
while (File.Exists(fileFullPaht))
...{
fileFullPaht += DateTime.Now.ToFileTime().ToString();
}
_stream = File.Create(fileFullPaht);
}
/**//// <summary>
/// 初始化
/// </summary>
/// <param name="firstBag">接收到的第一包数据</param>
/// <returns></returns>
public int Initialize(byte[] firstBag)
...{
int result = SetBaseInfo(firstBag);
creatFile();
_currentBag = 0;
return result;
}
/**//// <summary>
/// 写数据
/// </summary>
/// <param name="bin"></param>
public void Write(byte[] bin)
...{
_currentBag++;
long count = _fileSize -(_stream.Length + _readLen);
if (count > 0)
...{
_stream.Write(bin, 8, _readLen);
}
else
...{
_stream.Write(bin, 8, (int)(_readLen+count));
_stream.Close();
if (ReceivedFile != null) ReceivedFile(this);
}
}
}
}