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并发(四):缓存设计 在编写服务端大并发的应用程序,需要非常注意缓存设计,缓存的设计是一个折衷的结果,需要通过并发测试反复验证.有很多服务程序是在启动时申请足够的内存 ...
随机推荐
- [Ramda] Difference between R.converge and R.useWith
So what is Point-free function. Take a look this example: const getUpdatedPerson = (person) => R. ...
- hexo改造
一直在思考网站分类的问题. 用hexo默认的分类,并不利于用户直观的感受到网站的内容意图,尤其是hexo首页进入后是最近发表的文章列表.然后考虑开启多个hexo服务,每个hexo服务是一个分类内容,如 ...
- Spring MVC的RequestContextHolder使用误区 good
JShop简介:jshop是一套使用Java语言开发的B2C网店系统,致力于为个人和中小企业提供免费.好用的网店系统. 项目主页:http://git.oschina.net/dinguangx/js ...
- ThoughtWorks、Teambition、Trello、Slack、DevCloud 主流敏捷软件开发工具平台比较
在大公司做了6年程序员,2年项目经理的小王,正在创业公司迎来他焦虑的而立之年. 但是对于3个月前加入创业公司的决定,他现在有些烦躁和怀疑人生.在他过往的经验看来,公司新接的小项目,在过去的大公司里1个 ...
- 5.1 入门整合案例(SpringBoot+Spring-data-elasticsearch) ---- good
本节讲解SpringBoot与Spring-data-elasticsearch整合的入门案例. 一.环境搭建 新建maven项目,名字随意 pom.xml <parent> <gr ...
- 使用相对路径导入ado库的方法
作者:朱金灿 来源:http://blog.csdn.net/clever101 常用的导入ado库的语句: #import "c:\program files\common files\s ...
- MongoDB小结
教程 MongoDB MongoDB 是由C++语言编写的,是一个基于分布式文件存储的开源数据库系统.在高负载的情况下,添加更多的节点,可以保证服务器性能.MongoDB 旨在为WEB应用提供可扩展的 ...
- HDU 1143 Tri Tiling (递推)
Tri Tiling Time Limit: 2000/1000 MS (Java/Others) Memory Limit: 65536/32768 K (Java/Others) Total ...
- Java 9 特性
Java 8 发布三年多之后,已经于在2017年9月21日发布了. 你可能已经听说过 Java 9 的模块系统,但是这个新版本还有许多其它的更新. 这里有九个令人兴奋的新功能. 1. Java 平台级 ...
- VBS学习日记(二) 基础知识
VBScript 基础知识 一.变量 1.全部单引號后面的内容都被解释为凝视.(在vbsedit中ctrl+m凝视,反凝视ctrl+shift+m) 2.在 VBScript 中,变量的命名规则遵循标 ...