C#高性能大容量SOCKET并发(九):断点续传
上传断点续传
断点续传主要是用在上传或下载文件,一般做法是开始上传的时候,服务器返回上次已经上传的大小,如果上传完成,则返回-1;下载开始的时候,由客户端上报本地已经下载大小,服务器根据位置信息下发数据,因此上传下载协议都需要带Size大小,例如我们协议格式。
上传开始:
客户端->服务器
{
[Request]
Command=Upload
Dir=Dir #目录,全路径名
FileName=FileName #文件名(不包括路径)
}
服务器->客户端
{
[Response]
Command=Upload
Code= Error Code #错误码
Message=Message #如果出错,返回错误描述信息
FileSize=FileSize #已上传文件的大小,用于续传
}
因此在接收客户端上传请求时需要下发服务器上次接收到文件地址:
public bool DoUpload()
{
string dirName = "";
string fileName = "";
if (m_incomingDataParser.GetValue(ProtocolKey.DirName, ref dirName) & m_incomingDataParser.GetValue(ProtocolKey.FileName, ref fileName))
{
if (dirName == "")
dirName = Program.FileDirectory;
else
dirName = Path.Combine(Program.FileDirectory, dirName);
fileName = Path.Combine(dirName, fileName);
Program.Logger.Info("Start upload file: " + fileName);
if (m_fileStream != null) //关闭上次传输的文件
{
m_fileStream.Close();
m_fileStream = null;
m_fileName = "";
}
if (File.Exists(fileName))
{
if (!CheckFileInUse(fileName)) //检测文件是否正在使用中
{
m_fileName = fileName;
m_fileStream = new FileStream(fileName, FileMode.Open, FileAccess.ReadWrite);
m_fileStream.Position = m_fileStream.Length; //文件移到末尾
m_outgoingDataAssembler.AddSuccess();
m_outgoingDataAssembler.AddValue(ProtocolKey.FileSize, m_fileStream.Length);
}
else
{
m_outgoingDataAssembler.AddFailure(ProtocolCode.FileIsInUse, "");
Program.Logger.Error("Start upload file error, file is in use: " + fileName);
}
}
else
{
m_fileName = fileName;
m_fileStream = new FileStream(fileName, FileMode.OpenOrCreate, FileAccess.ReadWrite);
m_fileStream.Position = m_fileStream.Length; //文件移到末尾
m_outgoingDataAssembler.AddSuccess();
m_outgoingDataAssembler.AddValue(ProtocolKey.FileSize, m_fileStream.Length);
}
}
else
m_outgoingDataAssembler.AddFailure(ProtocolCode.ParameterError, "");
return DoSendResult();
}
下载断点续传
下载开始:
客户端->服务器
{
[Request]
Command=Download
Dir=Dir #目录,全路径名
FileName=FileName #文件名(不包括路径)
FileSize=FileSize #客户端本地文件大小,用于断点续传
PacketSize=PacketSize #下发数据包大小,单位为KB,用于速度测试
}
服务器->客户端
{
[Response]
Command= Download
Code= Error Code #错误码
Message=Message #如果出错,返回错误描述信息
}
public bool DoDownload()
{
string dirName = "";
string fileName = "";
Int64 fileSize = 0;
int packetSize = 0;
if (m_incomingDataParser.GetValue(ProtocolKey.DirName, ref dirName) & m_incomingDataParser.GetValue(ProtocolKey.FileName, ref fileName)
& m_incomingDataParser.GetValue(ProtocolKey.FileSize, ref fileSize) & m_incomingDataParser.GetValue(ProtocolKey.PacketSize, ref packetSize))
{
if (dirName == "")
dirName = Program.FileDirectory;
else
dirName = Path.Combine(Program.FileDirectory, dirName);
fileName = Path.Combine(dirName, fileName);
Program.Logger.Info("Start download file: " + fileName);
if (m_fileStream != null) //关闭上次传输的文件
{
m_fileStream.Close();
m_fileStream = null;
m_fileName = "";
m_sendFile = false;
}
if (File.Exists(fileName))
{
if (!CheckFileInUse(fileName)) //检测文件是否正在使用中
{
m_fileName = fileName;
m_fileStream = new FileStream(fileName, FileMode.Open, FileAccess.ReadWrite);
m_fileStream.Position = fileSize; //文件移到上次下载位置
m_outgoingDataAssembler.AddSuccess();
m_sendFile = true;
m_packetSize = packetSize;
}
else
{
m_outgoingDataAssembler.AddFailure(ProtocolCode.FileIsInUse, "");
Program.Logger.Error("Start download file error, file is in use: " + fileName);
}
}
else
{
m_outgoingDataAssembler.AddFailure(ProtocolCode.FileNotExist, "");
}
}
else
m_outgoingDataAssembler.AddFailure(ProtocolCode.ParameterError, "");
return DoSendResult();
}
多线程并发下载
断点续传的一个应用就是并发下载,做法是客户端起多个线程并发请求同一个文件,每个线程下文件的一部分,全部下载完成后,把每个数据块合并为一个文件。这个服务端和客户端协议都不需要修改,只是需要做下载逻辑的更改。
多线程并发上传
这个需要定义通讯来支持这个逻辑,主要是服务器要提供合并多个数据文件为一个文件的协议逻辑。
DEMO下载地址:http://download.csdn.net/detail/sqldebug_fan/7467745
免责声明:此代码只是为了演示C#完成端口编程,仅用于学习和研究,切勿用于商业用途。水平有限,C#也属于初学,错误在所难免,欢迎指正和指导。邮箱地址:fansheng_hx@163.com。
C#高性能大容量SOCKET并发(九):断点续传的更多相关文章
- C#高性能大容量SOCKET并发(转)
C#高性能大容量SOCKET并发(零):代码结构说明 C#高性能大容量SOCKET并发(一):IOCP完成端口例子介绍 C#高性能大容量SOCKET并发(二):SocketAsyncEventArgs ...
- C#高性能大容量SOCKET并发(十一):编写上传客户端
原文:C#高性能大容量SOCKET并发(十一):编写上传客户端 客户端封装整体框架 客户端编程基于阻塞同步模式,只有数据正常发送或接收才返回,如果发生错误则抛出异常,基于TcpClient进行封装,主 ...
- C#高性能大容量SOCKET并发(零):代码结构说明
原文:C#高性能大容量SOCKET并发(零):代码结构说明 C#版完成端口具有以下特点: 连接在线管理(提供在线连接维护,连接会话管理,数据接收,连接断开等相关事件跟踪): 发送数据智能合并(组件会根 ...
- C#高性能大容量SOCKET并发(十):SocketAsyncEventArgs线程模型
原文:C#高性能大容量SOCKET并发(十):SocketAsyncEventArgs线程模型 线程模型 SocketAsyncEventArgs编程模式不支持设置同时工作线程个数,使用的NET的IO ...
- C#高性能大容量SOCKET并发(七):协议字符集
原文:C#高性能大容量SOCKET并发(七):协议字符集 UTF-8 UTF-8是UNICODE的一种变长字符编码又称万国码,由Ken Thompson于1992年创建.现在已经标准化为RFC 362 ...
- C#高性能大容量SOCKET并发(六):超时Socket断开(守护线程)和心跳包
原文:C#高性能大容量SOCKET并发(六):超时Socket断开(守护线程)和心跳包 守护线程 在服务端版Socket编程需要处理长时间没有发送数据的Socket,需要在超时多长时间后断开连接,我们 ...
- C#高性能大容量SOCKET并发(五):粘包、分包、解包
原文:C#高性能大容量SOCKET并发(五):粘包.分包.解包 粘包 使用TCP长连接就会引入粘包的问题,粘包是指发送方发送的若干包数据到接收方接收时粘成一包,从接收缓冲区看,后一包数据的头紧接着前一 ...
- C#高性能大容量SOCKET并发(三):接收、发送
原文:C#高性能大容量SOCKET并发(三):接收.发送 异步数据接收有可能收到的数据不是一个完整包,或者接收到的数据超过一个包的大小,因此我们需要把接收的数据进行缓存.异步发送我们也需要把每个发送的 ...
- C#高性能大容量SOCKET并发(四):缓存设计
原文:C#高性能大容量SOCKET并发(四):缓存设计 在编写服务端大并发的应用程序,需要非常注意缓存设计,缓存的设计是一个折衷的结果,需要通过并发测试反复验证.有很多服务程序是在启动时申请足够的内存 ...
随机推荐
- Erlang中的record与宏
http://www.cnblogs.com/me-sa/archive/2011/07/20/erlang0006.html 在Erlang中使用Tuple ,数据项的顺序\数量都是确定的,一旦数据 ...
- Oracle中的游标(转)
Oracle中的游标有两种:显式游标.隐式游标.显示游标是用cursor...is命令定义的游标,它可以对查询语句(select)返回的多条记录进行处理,而隐式游标是在执行插入 (insert).删除 ...
- 【t059】序列
Time Limit: 1 second Memory Limit: 128 MB [问题描述] 生活中,大多数事物都是有序的,因为顺序的美是最令人陶醉的.所以现在RCDH看了不顺的东西就头痛.所以他 ...
- 让ProgressDialog在setCancelable(false)时按返回键可dismiss
最近发现Android4.0系统中ProgressDialog设置为setCancelable(true)时,点击ProgressDialog以外的区域也可以让ProgressDialog dismi ...
- WPF 自定义控件的坑(蠢的:自定义控件内容不显示)
原文:WPF 自定义控件的坑(蠢的:自定义控件内容不显示) 版权声明:本文为博主原创文章,未经博主允许不得转载. https://blog.csdn.net/koloumi/article/detai ...
- 广义逆高斯分布(Generalized Inverse Gaussian Distribution)及修正贝塞尔函数
1. PDF generalized inverse Gaussian distribution (GIG) 是一个三参数的连续型概率分布: f(x)=(a/b)p/22Kp(ab−−√)xp−1e− ...
- 使用XCA(X Certificate and key management)可视化项目经理SSL 凭证(4)--凭借自身的凭证管理中心的定义(Certificate Authority)签名证书申请
随着XCA(X Certificate and key management)可视化项目经理SSL 证书系列文章(2)和(3)中.我们学习了怎样用XCA(X Certificate and key m ...
- nginx配置http跳转https
配置相当简单,在配置文件头部加一行,如下: server { listen *:;//监听80端口 https://www.chenruhui.com$request_uri;//需要跳转的网页 } ...
- AntDesign Form表单字段校验的三种方式
1.使用getFieldDecorator的rules规则 最简单的方法就是使用getFieldDecorator中的rules验证.rules中定义校验规则,message为校验不通过时的提示文字. ...
- springboot 上传图片
1. 创建多层目录 创建多层目录要使用File的mkdirs()方法,其他可以使用mkdir()方法. 2. 文件大小限制 配置文件中,在spring1.4以后要使用 ` spring.http.mu ...