前面写了一个单文件传输的,后来发现当传送的文件大于设置的缓存空间时,文件就会出现丢包的现象,导致文件无法使用,所以为了适应大文件的传输,这里我将代码进行了下修改,实现大文件传输。

不过socket实现大文件传输有个缺点,由于传输过程是通过字节缓存发送,接受也是读写字节,导致整个传输过程效率不高,我尝试了一个169MB的视频文件传输,虽然传完了,但是耗时将近1小时。

因为计算机缓存有限,所以不可能开启太大的缓存来缓存数据的,所以当我们要发送文件较大的文件时我们就要进行分段处理,分段读取,分段发送保存。大家可以看到我们的两个窗口都是同步的,一遍在读取中,一遍就在写入中。如此反复的使用同一块缓存进行数据传递。

首先我们先进行循环读取文件信息,这里有个重要的就是做好标记,之前写 C#实战026:socket实现单文件传输时就有提到,通过在第一个字节做标记来区分我们传送的信息是什么信息,这个规则自己定义,只要客户端和服务端同步即可

这里我们把0定义成信息发送,1定义成文件发送,2定义成文件头信息发送

首先我们先需要把我们要发送的文件信息抛给服务器,这里主要需要文件的文件名和文件大小,这里我们只要在用文件流读取文件的时候将这些数据提取出来即可:

//1. 第一步:发送一个文件,表示文件名和长度,让客户端知道文件大小
string fileName = Path.GetFileName(filePath);//提取文件名
Console.WriteLine("发送的文件名是:" + fileName);//查看获取文件名是否正确
long fileLength = fsRead.Length;//获取文件长度
Console.WriteLine("发送的文件长度为:"+fileLength);//查看文件长度是否正确
string totalMsg = string.Format("{0}-{1}", fileName, fileLength);//将文件名和文件长度存入一条数据中
byte[] buffer = Encoding.UTF8.GetBytes(totalMsg); //将字符串转换成字节数组
byte[] newBuffer = new byte[buffer.Length + 1];//新建字节数组,增加一个字节空间
newBuffer[0] = 2;//将第一个字节标记成2,代表为文件头信息
Buffer.BlockCopy(buffer, 0, newBuffer, 1, buffer.Length);//偏移复制字节数组
socketClient.Send(newBuffer);//发送文件文件名和长度发过去

既然是循环写入,我们就要记录当前文件的数据大小和已读取的数据信息,这样循环才有终点,定义一个5M缓存区。

byte[] Filebuffer = new byte[1024 * 1024 * 5];//定义5MB的缓存空间(1024字节(b)=1千字节(kb))
int readLength = 0;  //定义读取的长度
bool firstRead = true;//定义首次读取的状态
long sentFileLength = 0;//定义发送的长度

接下里解释对文件进行分包发送了,这里唯一要注意的就是第一次发送的时候要为文件价格标记,也就是第一个数据包前加标记,这样服务端才好去识别该数据是什么数据,然后做对应的处理。

while (readLength> 0 && sentFileLength < fileLength)
{sentFileLength += readLength;//计算已读取文件大小//第一次发送的字节流上加个前缀1if (firstRead){byte[] firstBuffer = new byte[readLength + 1];//这个操作同样也是用来标记文件的firstBuffer[0] = 1;//将第一个字节标记成1,代表为文件Buffer.BlockCopy(buffer, 0, firstBuffer, 1, readLength);//偏移复制字节数组socketClient.Send(firstBuffer, 0, readLength + 1, SocketFlags.None);Console.WriteLine("第一次读取数据成功,在前面添加一个标记");//发送文件数据包firstRead = false;//切换状态,避免再次进入continue;}socketClient.Send(buffer, 0, readLength, SocketFlags.None);//继续发送剩下的数据包Console.WriteLine("{0}: 已发送数据:{1}/{2}", socketClient.RemoteEndPoint, sentFileLength, fileLength);//查看发送进度
}
fsRead.Close();//关闭文件流
Console.WriteLine("发送完成");//提示发送完毕

接下来在可以在服务端来接受数据了,同样在处理数据的时候要把第一次数据分开,因为第一组数据中添加一个标记符,所以我们在写数据的时候要截取标记后面的数据。

if (buffer[0] == 1)//1对应文件信息
{SaveFileDialog sfDialog = new SaveFileDialog();//创建SaveFileDialog实例string spath = @"C:\Users\admin\Desktop";//制定存储路径string savePath = Path.Combine(spath, recStr);//获取存储路径及文件名int rec = 0;//定义获取接受数据的长度初始值long recFileLength = 0;bool firstWrite = true;using (FileStream fs = new FileStream(savePath, FileMode.Create, FileAccess.Write)){while (recFileLength < fileLength)//判断读取文件长度是否小于总文件长度{if (firstWrite)//第一次写入时{fs.Write(buffer, 1, firstRcv - 1);//截取字节数据写入文件中fs.Flush();//清空缓存信息recFileLength += firstRcv - 1;//记录已获取的数据大小firstWrite = false;//切换状态}else{rec = socketServer.Receive(buffer);//继续接收文件并存入缓存fs.Write(buffer, 0, rec);//将缓存中的数据写入文件中fs.Flush();//清空缓存信息recFileLength += rec;//继续记录已获取的数据大小}Console.WriteLine("{0}: 已接收数据:{1}/{2}", socketServer.RemoteEndPoint, recFileLength, fileLength);//查看已接受数据进度}fs.Close();}Console.WriteLine("保存成功!!!!");
}

我把源码传在CSDN了,有兴趣的可以下载:  Socket传输大文件(发送与接收源码)

首发百度经验 :   C#实战027:socket实现大文件传输

欢迎关注本人的公众号:编程手札,文章也会在公众号更新

C#实战027:socket实现大文件传输相关推荐

  1. linux 传输大文件大小,Linux大文件传输(转)

    我们经常需要在机器之间传输文件.比如备份,复制数据等等.这个是很常见,也是很简单的.用scp或者rsync就能很好的完成任务.但是如果文件很大,需要占用一些传输时间的时候,怎样又快又好地完成任务就很重 ...

  2. html大文件传输,socket大文件传输

    遇到了在c#中socket如何实现大文件传输 接收端 private void Receive(Socket socket) { NetworkStream ns = new NetworkStrea ...

  3. c++ udp多线程 例子_[内附完整源码和文档] 基于udp实现tcp功能进行大文件传输

    一.项目要求 Please choose one of following programing languages: C, C++, Java, Python; 本项目采用的是python3.6 L ...

  4. 邮箱附件、QQ、微信等社交工具大文件传输解决方案

    工具说明:适用于邮箱附件.QQ.微信.钉钉.网盘等场景的大文件分割存储和传输. 下载地址:https://download.csdn.net/download/hj960511/85012515 作者 ...

  5. java rmi 文件传输_JAVA-RMI实现大文件传输

    在使用java-rmi的过程中,必然会遇到一个文件上传的问题,由于在rmi中无法传输文件流(比如rmi中的方法参数不能是FileInputStream之类的),那么我们只好选择一种折中的办法,就是先用 ...

  6. Linux、Windows都适用的跨国传输、大文件传输软件:飞驰传输

    随着"走出去"战略的实施,中国越来越多的企业走向国外,跨国企业将是大的潮流和趋势.跨国企业的分支机构遍及全球各地,员工来自多个国家,使用不同的语言.由于各地IT基础设施建设水平和使 ...

  7. 如何分发大文件、大文件传输解决方案

    随着云计算.大数据技术不断发展,4K 视频.虚拟现实(VR).视频直播等互联网应用领域不断升级更新,企业网.数据中心规模持续扩大,企业拥有的数据急剧增长,海量文件随之产生. 同时,互联网时代,众多行业 ...

  8. 基于UDP的企业级大文件传输体系

    在信息技术与互联网技术快速发展的今天,很多企业,特别是大中型企业都建设了林林总总的信息系统.这些信息系统助推企业实现了业务的快速发展.办公管理的科学高效,为企业创造了巨大的经济价值.这些信息系统在功能 ...

  9. 大文件传输软件的优势你了解吗?

    2012年以来,大数据(big data)一词越来越多地被提及,人们用它来描述和定义信息爆炸时代产生的海量数据,并命名与之相关的技术发展与创新.数据正在迅速膨胀并变大,它决定着企业的未来发展.企业面临 ...

最新文章

  1. 糟糕的css用法 1
  2. 菜鸟学前端之初入江湖
  3. 接口返回时间较长,如何提高响应速度?
  4. RPNet++:人脸对齐faceAlignment和基于CNN的三维人脸恢复
  5. SAP Fiori 应用的本地 sandbox Launchpad - 出于测试用途
  6. php数组o m n mn,O(m + n)和O(mn)之间的区别?
  7. android sqlite 示例,android SQLite数据库使用示例
  8. 《大数据》2015年第3期“专题”——网络表示学习(上)
  9. Ubuntu Apache 不同端口监听不同站点
  10. Julia:String和ASCIIString
  11. 【优化预测】基于matlab差分进化算法优化BP神经网络预测【含Matlab源码 1315期】
  12. pycharm-perl脚本
  13. MAX422与422转USB及485以及232接线方法
  14. 基于华为SMProxy开发cmpp2.0(跳坑版)
  15. 自抗扰控制中的扩张状态观测器收敛性分析1
  16. class balanced loss pytorch 实现
  17. mysql8.0 无法加载身份验证插件“缓存_sha2_密码” 问题解决方法
  18. 【关于2022年卡塔尔世界杯】
  19. 【转】《Cascaded Pyramid Network for Multi-Person Pose Estimation》--旷世2017COCO keypoints冠军论文解读
  20. Python 安装opencv-python模块

热门文章

  1. 【手撕算法】HC显著性检测算法
  2. Visual Studio 2022 修改主题和字体
  3. 颜色代码六位十六进制字符_8位十六进制颜色
  4. 什么是流动性质押?什么是农场质押?
  5. 自动化测试类型有哪些?是怎么分类的
  6. 房源管理系统服务器,房源管理系统服务器
  7. 怎么音频转换成文字?其实特别简单,告诉你详细图文步骤
  8. 总结:shell中的if条件判断
  9. Python的ORM框架Peewee使用入门(二)
  10. hdr与sdr_sdr和hdr区别