C#Socket 文件传输,支持断点续传
来源:互联网 发布:数据恢复网 编辑:程序博客网 时间:2024/05/16 01:03
最近做一个程序需要传送文件,在网上找了好久也没找到好用的方案,于是自己写了一个,与大家分享,希望大家帮忙改进,拍砖欢迎~
文件采取分块发送,每块单独校验,能够保证文件的完整性.同时还提供磁盘缓存功能.
经过实际测试,通过局域网(有线和WiFi)传送一个5G左右的文件取得成功.
最大缺点是CPU占用率过高,测试中发送端(939AMD3000+)达到40%,接收端(双核T9600、939AMD3200+)分别为15%和35%左右.
性能确实还有待改进....
贴出部分代码,其他的放附件里:
文件采取分块发送,每块单独校验,能够保证文件的完整性.同时还提供磁盘缓存功能.
经过实际测试,通过局域网(有线和WiFi)传送一个5G左右的文件取得成功.
最大缺点是CPU占用率过高,测试中发送端(939AMD3000+)达到40%,接收端(双核T9600、939AMD3200+)分别为15%和35%左右.
性能确实还有待改进....
贴出部分代码,其他的放附件里:
using System;
using System.Collections.Generic;
using System.IO;
using System.Linq;
using System.Net.Sockets;
using System.Text;
using System.Threading;
namespace Takamachi660.FileTransmissionSolution
{//Version 0.6
CRC32算法
一些常量和扩展方法
一些委托
文件区块类
事件参数类
文件区块抽象集合类
#region 文件传输基类
publicabstractclass FileTransmission : IDisposable
{
internal FileStream _FileStream;
//internal readonly TransmissionMode _Mode;
///<summary>
/// 总区块数
///</summary>
internalint _TotalBlock;
///<summary>
/// 最后一个区块的大小
///</summary>
internalint _LastBlockSize;
internal List<int> _FinishedBlock;
internalbyte[] ReceiveBuf;
internal Socket _Socket;
internal EventWaitHandle _WaitHandle;
internalbool _IsAlive;
internal FileBlockCollection _Blocks;
internal DateTime _StartTime;
///<summary>
/// 上一个区块完成的时间
///</summary>
internal DateTime _PriorBlockTime;
internaldouble _ByteSpeed;
///<summary>
/// 获取或设置一个值,该值指示是否启用磁盘缓存
///</summary>
publicbool EnabledIOBuffer
{
get{return _Blocks._EnabledIOBuffer; }
set{ _Blocks.EnabledIOBuffer= value; }
}
///<summary>
/// 获取或设置磁盘缓存的大小(单位:区块数)
///</summary>
publicint IOBufferSize
{
get{return _Blocks._IOBufferSize; }
set
{
if (!_Blocks._EnabledIOBuffer)
thrownew InvalidOperationException("IOBuffer is not enabled!");
_Blocks._IOBufferSize= value;
}
}
///<summary>
/// 获取当前磁盘缓存中的区块数
///</summary>
publicint CurrentIOBufferSize
{
get
{
if (!_Blocks._EnabledIOBuffer)
return0;
return _Blocks._IOBuffer.Count;
}
}
///<summary>
/// 获取或设置该传输的目标连接
///</summary>
public Socket Socket
{
get{return _Socket; }
set
{
try
{
if (value.ProtocolType!= ProtocolType.Tcp)
thrownew ArgumentException("Socket Protocol must be TCP","Socket");
_Socket= value;
_Socket.ReceiveBufferSize= _Socket.SendBufferSize= Consts.NetBlockMaxSize;
}
catch (Exception ex)
{
OnErrorOccurred(ex);
}
}
}
///<summary>
/// 获取与此传输关联的文件流
///</summary>
public FileStream FileStream{get{return _FileStream; } }
///<summary>
/// 获取或设置文件路径
///</summary>
publicstring FilePath{get;set; }
///<summary>
/// 获取或设置文件名
///</summary>
publicstring FileName{get;set; }
///<summary>
/// 获取或设置文件名(包括路径)
///</summary>
publicstring FullFileName
{
get
{
try
{
return FilePath.TrimEnd('\\')+"\\"+ FileName;
}
catch (Exception ex)
{
OnErrorOccurred(ex);
returnnull;
}
}
set
{
try
{
int i= value.LastIndexOf('\\');
if (i>0)
FilePath= value.Substring(0, i);
else
FilePath= Environment.CurrentDirectory;
FileName= value.Substring(i+1);
}
catch (Exception ex)
{
OnErrorOccurred(ex);
}
}
}
///<summary>
/// 一个区块完成时发生
///</summary>
publicevent BlockFinishedEventHandler BlockFinished;
///<summary>
/// 全部完成时发生
///</summary>
publicevent EventHandler AllFinished;
///<summary>
/// 连接中断时发生
///</summary>
publicevent EventHandler ConnectLost;
///<summary>
/// 出现错误时发生
///</summary>
publicevent FileTransmissionErrorOccurEventHandler ErrorOccurred;
///<summary>
/// 获取一个值,该值指示传输是否正在进行
///</summary>
publicbool IsAlive{get{return _IsAlive; } }
///<summary>
/// 获取传输开始的时间
///</summary>
public DateTime StartTime{get{return _StartTime; } }
///<summary>
/// 获取已用时
///</summary>
public TimeSpan TimePast{get{return DateTime.Now- _StartTime; } }
///<summary>
/// 获取估计剩余时间
///</summary>
publicabstract TimeSpan TimeRemaining{get; }
///<summary>
/// 获取平均速率(区块/秒)
///</summary>
publicdouble BlockAverSpeed
{
get
{
return _FinishedBlock.Count/ TimePast.TotalSeconds;
}
}
///<summary>
/// 获取平均速率(字节/秒)
///</summary>
publicdouble ByteAverSpeed
{
get
{
return BlockAverSpeed* Consts.BlockSize;
}
}
///<summary>
/// 获取平均速率(千字节/秒)
///</summary>
publicdouble KByteAverSpeed
{
get
{
return ByteAverSpeed/1024;
}
}
///<summary>
/// 获取瞬时速率(字节/秒)
///</summary>
publicdouble ByteSpeed
{
get
{
return _ByteSpeed;
}
}
///<summary>
/// 获取瞬时速率(千字节/秒)
///</summary>
publicdouble KByteSpeed
{
get
{
return _ByteSpeed/1024;
}
}
///<summary>
/// 获取文件总长度
///</summary>
publiclong TotalSize
{
get
{
return (long)(_TotalBlock-1)* (long)Consts.BlockSize+ (long)_LastBlockSize;
}
}
///<summary>
/// 获取已完成的数据长度
///</summary>
publicabstractlong FinishedSize{get; }
///<summary>
/// 获取进度值(%)
///</summary>
publicdouble Progress
{
get
{
return ((double)FinishedSize/ (double)TotalSize)*100;
}
}
///<summary>
/// 获取该传输的区块集合
///</summary>
public FileBlockCollection Blocks{get{return _Blocks; } }
///<summary>
/// 默认构造函数
///</summary>
public FileTransmission()
{
_FinishedBlock=new List<int>();
_WaitHandle=new EventWaitHandle(false, EventResetMode.ManualReset);
_Blocks=new FileBlockCollection(this);
}
///<summary>
/// 构造函数
///</summary>
///<param name="FilePath">文件路径</param>
///<param name="FileName">文件名</param>
public FileTransmission(string FilePath,string FileName)
{
_FinishedBlock=new List<int>();
_WaitHandle=new EventWaitHandle(true, EventResetMode.ManualReset);
_Blocks=new FileBlockCollection(this);
this.FilePath= FilePath;
this.FileName= FileName;
}
///<summary>
/// 初始化接收缓存
///</summary>
internalvoid InitializeReceiveBuf()
{
try
{
ReceiveBuf=newbyte[_Socket.ReceiveBufferSize];
}
catch (Exception ex)
{
OnErrorOccurred(ex);
}
}
///<summary>
/// 开始异步接收
///</summary>
internalabstract IAsyncResult BeginReceive();
///<summary>
/// 开始传输
///</summary>
publicvirtualvoid Start()
{
try
{
_IsAlive=true;
_StartTime= DateTime.Now;
_WaitHandle.Reset();
}
catch (Exception ex)
{
OnErrorOccurred(ex);
}
}
///<summary>
/// 中止传输
///</summary>
///<param name="ShutDownSocket">是否关闭Socket</param>
publicvirtualvoid Stop(bool ShutDownSocket)
{
try
{
_IsAlive=false;
_FileStream.Close();
_FileStream=null;
_WaitHandle.Set();
if (ShutDownSocket)
{
_Socket.Shutdown(SocketShutdown.Both);
_Socket.Close();
}
}
catch (Exception ex)
{
OnErrorOccurred(ex);
}
}
///<summary>
/// 异步中止传输,不关闭Socket
///</summary>
internalvoid Stop()
{
new Delegate_Void_Bool(Stop).BeginInvoke(false,null,null);
}
///<summary>
/// 等待传输完成
///</summary>
publicbool WaitForExit()
{
return _WaitHandle.WaitOne();
}
///<summary>
/// 等待传输完成
///</summary>
publicbool WaitForExit(int millisecondsTimeout,bool exitContext)
{
return _WaitHandle.WaitOne(millisecondsTimeout, exitContext);
}
///<summary>
/// 等待传输完成
///</summary>
publicbool WaitForExit(TimeSpan timeout,bool exitContext)
{
return _WaitHandle.WaitOne(timeout, exitContext);
}
internalvirtualvoid OnBlockFinished(int BlockIndex)
{
if (!_FinishedBlock.Exists(a=> a== BlockIndex))
_FinishedBlock.Add(BlockIndex);
if (BlockIndex== _TotalBlock-1)
_ByteSpeed= _LastBlockSize/ (DateTime.Now- _PriorBlockTime).TotalSeconds;
else
_ByteSpeed= Consts.BlockSize/ (DateTime.Now- _PriorBlockTime).TotalSeconds;
_PriorBlockTime= DateTime.Now;
if (BlockFinished!=null)
BlockFinished(this,new BlockFinishedEventArgs(BlockIndex));
}
internalvirtualvoid OnConnectLost()
{
if (!_IsAlive)
return;
Stop();
if (ConnectLost!=null)
ConnectLost(this,new EventArgs());
}
///<summary>
/// 同步发送字符串
///</summary>
publicint SendString(string str)
{
try
{
return _Socket.EndSend(BeginSendString(str,null,null));
}
catch (SocketException)
{
OnConnectLost();
return0;
}
catch (Exception ex)
{
OnErrorOccurred(ex);
return0;
}
}
///<summary>
/// 异步发送字符串并使用默认的回调方法
///</summary>
publicvoid SendStringAsync(string str)
{
BeginSendString(str, SendCallback,null);
}
///<summary>
/// 异步发送字符串并使用指定的的回调方法和参数
///</summary>
public IAsyncResult BeginSendString(string str, AsyncCallback callback, object state)
{
try
{
if (!_IsAlive)
thrownew InvalidOperationException("Is Not Alive");
byte[] ToSend= str.ToBytes();
return _Socket.BeginSend(ToSend,0, ToSend.Length, SocketFlags.None, callback, state);
}
catch (SocketException)
{
OnConnectLost();
returnnull;
}
catch (Exception ex)
{
OnErrorOccurred(ex);
returnnull;
}
}
internalvoid SendCallback(IAsyncResult ar)
{
try
{
_Socket.EndSend(ar);
}
catch (SocketException)
{
OnConnectLost();
}
catch (Exception ex)
{
OnErrorOccurred(ex);
}
if (ar.AsyncState!=null)
{
if (ar.AsyncStateisint)
{
OnBlockFinished((int)ar.AsyncState);
}
}
}
internalvirtualvoid OnAllFinished()
{
if (AllFinished!=null)
AllFinished(this,new EventArgs());
}
internalvirtualvoid OnErrorOccurred(Exception innerException)
{
FileTransmissionErrorOccurEventArgs eventargs=new FileTransmissionErrorOccurEventArgs(innerException);
if (ErrorOccurred!=null)
ErrorOccurred(this, eventargs);
if (!eventargs.Continue)
throw innerException;
}
void System.IDisposable.Dispose()
{
_FileStream.Close();
_Socket.Close();
}
}
#endregion
发送端类
接收端类
}
using System.Collections.Generic;
using System.IO;
using System.Linq;
using System.Net.Sockets;
using System.Text;
using System.Threading;
namespace Takamachi660.FileTransmissionSolution
{//Version 0.6
CRC32算法
一些常量和扩展方法
一些委托
文件区块类
事件参数类
文件区块抽象集合类
#region 文件传输基类
publicabstractclass FileTransmission : IDisposable
{
internal FileStream _FileStream;
//internal readonly TransmissionMode _Mode;
///<summary>
/// 总区块数
///</summary>
internalint _TotalBlock;
///<summary>
/// 最后一个区块的大小
///</summary>
internalint _LastBlockSize;
internal List<int> _FinishedBlock;
internalbyte[] ReceiveBuf;
internal Socket _Socket;
internal EventWaitHandle _WaitHandle;
internalbool _IsAlive;
internal FileBlockCollection _Blocks;
internal DateTime _StartTime;
///<summary>
/// 上一个区块完成的时间
///</summary>
internal DateTime _PriorBlockTime;
internaldouble _ByteSpeed;
///<summary>
/// 获取或设置一个值,该值指示是否启用磁盘缓存
///</summary>
publicbool EnabledIOBuffer
{
get{return _Blocks._EnabledIOBuffer; }
set{ _Blocks.EnabledIOBuffer= value; }
}
///<summary>
/// 获取或设置磁盘缓存的大小(单位:区块数)
///</summary>
publicint IOBufferSize
{
get{return _Blocks._IOBufferSize; }
set
{
if (!_Blocks._EnabledIOBuffer)
thrownew InvalidOperationException("IOBuffer is not enabled!");
_Blocks._IOBufferSize= value;
}
}
///<summary>
/// 获取当前磁盘缓存中的区块数
///</summary>
publicint CurrentIOBufferSize
{
get
{
if (!_Blocks._EnabledIOBuffer)
return0;
return _Blocks._IOBuffer.Count;
}
}
///<summary>
/// 获取或设置该传输的目标连接
///</summary>
public Socket Socket
{
get{return _Socket; }
set
{
try
{
if (value.ProtocolType!= ProtocolType.Tcp)
thrownew ArgumentException("Socket Protocol must be TCP","Socket");
_Socket= value;
_Socket.ReceiveBufferSize= _Socket.SendBufferSize= Consts.NetBlockMaxSize;
}
catch (Exception ex)
{
OnErrorOccurred(ex);
}
}
}
///<summary>
/// 获取与此传输关联的文件流
///</summary>
public FileStream FileStream{get{return _FileStream; } }
///<summary>
/// 获取或设置文件路径
///</summary>
publicstring FilePath{get;set; }
///<summary>
/// 获取或设置文件名
///</summary>
publicstring FileName{get;set; }
///<summary>
/// 获取或设置文件名(包括路径)
///</summary>
publicstring FullFileName
{
get
{
try
{
return FilePath.TrimEnd('\\')+"\\"+ FileName;
}
catch (Exception ex)
{
OnErrorOccurred(ex);
returnnull;
}
}
set
{
try
{
int i= value.LastIndexOf('\\');
if (i>0)
FilePath= value.Substring(0, i);
else
FilePath= Environment.CurrentDirectory;
FileName= value.Substring(i+1);
}
catch (Exception ex)
{
OnErrorOccurred(ex);
}
}
}
///<summary>
/// 一个区块完成时发生
///</summary>
publicevent BlockFinishedEventHandler BlockFinished;
///<summary>
/// 全部完成时发生
///</summary>
publicevent EventHandler AllFinished;
///<summary>
/// 连接中断时发生
///</summary>
publicevent EventHandler ConnectLost;
///<summary>
/// 出现错误时发生
///</summary>
publicevent FileTransmissionErrorOccurEventHandler ErrorOccurred;
///<summary>
/// 获取一个值,该值指示传输是否正在进行
///</summary>
publicbool IsAlive{get{return _IsAlive; } }
///<summary>
/// 获取传输开始的时间
///</summary>
public DateTime StartTime{get{return _StartTime; } }
///<summary>
/// 获取已用时
///</summary>
public TimeSpan TimePast{get{return DateTime.Now- _StartTime; } }
///<summary>
/// 获取估计剩余时间
///</summary>
publicabstract TimeSpan TimeRemaining{get; }
///<summary>
/// 获取平均速率(区块/秒)
///</summary>
publicdouble BlockAverSpeed
{
get
{
return _FinishedBlock.Count/ TimePast.TotalSeconds;
}
}
///<summary>
/// 获取平均速率(字节/秒)
///</summary>
publicdouble ByteAverSpeed
{
get
{
return BlockAverSpeed* Consts.BlockSize;
}
}
///<summary>
/// 获取平均速率(千字节/秒)
///</summary>
publicdouble KByteAverSpeed
{
get
{
return ByteAverSpeed/1024;
}
}
///<summary>
/// 获取瞬时速率(字节/秒)
///</summary>
publicdouble ByteSpeed
{
get
{
return _ByteSpeed;
}
}
///<summary>
/// 获取瞬时速率(千字节/秒)
///</summary>
publicdouble KByteSpeed
{
get
{
return _ByteSpeed/1024;
}
}
///<summary>
/// 获取文件总长度
///</summary>
publiclong TotalSize
{
get
{
return (long)(_TotalBlock-1)* (long)Consts.BlockSize+ (long)_LastBlockSize;
}
}
///<summary>
/// 获取已完成的数据长度
///</summary>
publicabstractlong FinishedSize{get; }
///<summary>
/// 获取进度值(%)
///</summary>
publicdouble Progress
{
get
{
return ((double)FinishedSize/ (double)TotalSize)*100;
}
}
///<summary>
/// 获取该传输的区块集合
///</summary>
public FileBlockCollection Blocks{get{return _Blocks; } }
///<summary>
/// 默认构造函数
///</summary>
public FileTransmission()
{
_FinishedBlock=new List<int>();
_WaitHandle=new EventWaitHandle(false, EventResetMode.ManualReset);
_Blocks=new FileBlockCollection(this);
}
///<summary>
/// 构造函数
///</summary>
///<param name="FilePath">文件路径</param>
///<param name="FileName">文件名</param>
public FileTransmission(string FilePath,string FileName)
{
_FinishedBlock=new List<int>();
_WaitHandle=new EventWaitHandle(true, EventResetMode.ManualReset);
_Blocks=new FileBlockCollection(this);
this.FilePath= FilePath;
this.FileName= FileName;
}
///<summary>
/// 初始化接收缓存
///</summary>
internalvoid InitializeReceiveBuf()
{
try
{
ReceiveBuf=newbyte[_Socket.ReceiveBufferSize];
}
catch (Exception ex)
{
OnErrorOccurred(ex);
}
}
///<summary>
/// 开始异步接收
///</summary>
internalabstract IAsyncResult BeginReceive();
///<summary>
/// 开始传输
///</summary>
publicvirtualvoid Start()
{
try
{
_IsAlive=true;
_StartTime= DateTime.Now;
_WaitHandle.Reset();
}
catch (Exception ex)
{
OnErrorOccurred(ex);
}
}
///<summary>
/// 中止传输
///</summary>
///<param name="ShutDownSocket">是否关闭Socket</param>
publicvirtualvoid Stop(bool ShutDownSocket)
{
try
{
_IsAlive=false;
_FileStream.Close();
_FileStream=null;
_WaitHandle.Set();
if (ShutDownSocket)
{
_Socket.Shutdown(SocketShutdown.Both);
_Socket.Close();
}
}
catch (Exception ex)
{
OnErrorOccurred(ex);
}
}
///<summary>
/// 异步中止传输,不关闭Socket
///</summary>
internalvoid Stop()
{
new Delegate_Void_Bool(Stop).BeginInvoke(false,null,null);
}
///<summary>
/// 等待传输完成
///</summary>
publicbool WaitForExit()
{
return _WaitHandle.WaitOne();
}
///<summary>
/// 等待传输完成
///</summary>
publicbool WaitForExit(int millisecondsTimeout,bool exitContext)
{
return _WaitHandle.WaitOne(millisecondsTimeout, exitContext);
}
///<summary>
/// 等待传输完成
///</summary>
publicbool WaitForExit(TimeSpan timeout,bool exitContext)
{
return _WaitHandle.WaitOne(timeout, exitContext);
}
internalvirtualvoid OnBlockFinished(int BlockIndex)
{
if (!_FinishedBlock.Exists(a=> a== BlockIndex))
_FinishedBlock.Add(BlockIndex);
if (BlockIndex== _TotalBlock-1)
_ByteSpeed= _LastBlockSize/ (DateTime.Now- _PriorBlockTime).TotalSeconds;
else
_ByteSpeed= Consts.BlockSize/ (DateTime.Now- _PriorBlockTime).TotalSeconds;
_PriorBlockTime= DateTime.Now;
if (BlockFinished!=null)
BlockFinished(this,new BlockFinishedEventArgs(BlockIndex));
}
internalvirtualvoid OnConnectLost()
{
if (!_IsAlive)
return;
Stop();
if (ConnectLost!=null)
ConnectLost(this,new EventArgs());
}
///<summary>
/// 同步发送字符串
///</summary>
publicint SendString(string str)
{
try
{
return _Socket.EndSend(BeginSendString(str,null,null));
}
catch (SocketException)
{
OnConnectLost();
return0;
}
catch (Exception ex)
{
OnErrorOccurred(ex);
return0;
}
}
///<summary>
/// 异步发送字符串并使用默认的回调方法
///</summary>
publicvoid SendStringAsync(string str)
{
BeginSendString(str, SendCallback,null);
}
///<summary>
/// 异步发送字符串并使用指定的的回调方法和参数
///</summary>
public IAsyncResult BeginSendString(string str, AsyncCallback callback, object state)
{
try
{
if (!_IsAlive)
thrownew InvalidOperationException("Is Not Alive");
byte[] ToSend= str.ToBytes();
return _Socket.BeginSend(ToSend,0, ToSend.Length, SocketFlags.None, callback, state);
}
catch (SocketException)
{
OnConnectLost();
returnnull;
}
catch (Exception ex)
{
OnErrorOccurred(ex);
returnnull;
}
}
internalvoid SendCallback(IAsyncResult ar)
{
try
{
_Socket.EndSend(ar);
}
catch (SocketException)
{
OnConnectLost();
}
catch (Exception ex)
{
OnErrorOccurred(ex);
}
if (ar.AsyncState!=null)
{
if (ar.AsyncStateisint)
{
OnBlockFinished((int)ar.AsyncState);
}
}
}
internalvirtualvoid OnAllFinished()
{
if (AllFinished!=null)
AllFinished(this,new EventArgs());
}
internalvirtualvoid OnErrorOccurred(Exception innerException)
{
FileTransmissionErrorOccurEventArgs eventargs=new FileTransmissionErrorOccurEventArgs(innerException);
if (ErrorOccurred!=null)
ErrorOccurred(this, eventargs);
if (!eventargs.Continue)
throw innerException;
}
void System.IDisposable.Dispose()
{
_FileStream.Close();
_Socket.Close();
}
}
#endregion
发送端类
接收端类
}
VS2008完整项目文件,包括类库和一个简单的Demo:
/Files/takamachi660/SendFileTest_v0.6.rar
- C#Socket 文件传输,支持断点续传
- C#Socket 文件传输,支持断点续传
- C#Socket 文件传输,支持断点续传
- 一个C#文件传输模块,支持断点续传
- C#Socket文件传输查询
- C语言socket 蓝牙文件传输
- C 语言实现文件传输 (socket实现)
- Linux下C语言Socket实现文件传输
- C#: 实现支持断点续传多线程下载的
- C++/php 文件上传,支持断点续传
- C#: 实现支持断点续传多线程下载
- Socket文件传输
- Socket文件传输
- Socket文件传输
- socket文件传输
- PHP 大文件下载,文件传输,支持断点续传。 2g以上超大文件也有效
- vc++ socket实现的支持断点续传的下载器
- vc++ socket实现的支持断点续传的下载器
- OSCACHE
- 使用MFC操作EXCEL文件
- 50个必备的实用jQuery代码段
- 黑马程序员__JDBC事务及将结果封装成对象
- C# .NET FTP上传文件夹操作
- C#Socket 文件传输,支持断点续传
- Hibernate配置文件属性---事务属性
- 持续集成学习笔记-入门篇(8)成果管理自动化(二):maven项目站点管理
- 小米1代成本到底多少钱?一笔一划算出来!
- Block media recovery BMR OCP-043
- ARM Cortex-M3 学习笔记(2)
- 详解java类的生命周期
- asp.net 图片防盗链
- 坐标变换