socket发送接收大文件

xiaxiaoying2012 2017-03-13 11:06:35
利用socket做一个文件发送和接受的应用,现在客户端向服务端发送一个几十兆的文件,利用循环,客户端每次都只向服务端发送1024个字节的数据流,所以需要循环的次数非常多,现在遇到了一个问题,客户端向服务端循环发送了1380次左右次数的数据之后,就不能再继续发送了,我客户端利用同步发送数据的,服务端试了异步接收数据和同步接收数据,结果都是这样的,循环发送接收数据的次数都没办法超过1380次,希望有大神帮忙解惑一下
...全文
299 14 打赏 收藏 转发到动态 举报
写回复
用AI写文章
14 条回复
切换为时间正序
请发表友善的回复…
发表回复
qq_41769287 2019-05-15
  • 打赏
  • 举报
回复
楼主我也遇到了跟你一样的问题,能分享一下你写的代码吗?
全栈极简 2017-03-13
  • 打赏
  • 举报
回复
你的1380次数是怎么得到的,不能再继续发送有什么错误?此外把1024放大到4096或者更大试试。
xiaxiaoying2012 2017-03-13
  • 打赏
  • 举报
回复
找到原因了,服务端每次收到消息的时候都会向客户端发送消息,但是我的客户端接收消息的代码写错了,只能接收一次消息,导致了服务端多次发送消息,而客户端又没有做接收消息的处理,导致了每次客户端和服务端在收发消息达到一定次数的时候没办法再进行下去了
xiaxiaoying2012 2017-03-13
  • 打赏
  • 举报
回复
public void WriteBuffer(byte[] buffer,int buffersize,Socket socket) { try { //FileStream fs = File.OpenWrite("D:\\a.txt"); byte[] guid = new byte[36]; Array.Copy(buffer, guid, 36); byte[] blockNum = new byte[10]; Array.Copy(buffer, 36, blockNum, 0, 10); int blocknum = int.Parse(Encoding.UTF8.GetString(blockNum)); FileState filestate = fss[Encoding.UTF8.GetString(guid)]; FileStream fs = filestate.Fstream; fs.Seek(filestate.GetCurrentInsertPosition(blocknum), SeekOrigin.Begin); long position = fs.Length; fs.Position = position; fs.Write(buffer, 46, buffersize - 46); fs.Flush(); filestate.AddBufferBlock(blocknum, buffersize - 46); //Console.WriteLine("源文件大小:" + filestate.FileSize + " 已接受大小:" + fs.Length); if (filestate.FileSize == fs.Length) { fs.Dispose(); fs.Close(); socket.Send(Encoding.UTF8.GetBytes("finish")); //向客户端发送文件已全部读取完毕的信号 } socket.Send(blockNum.Concat(Encoding.UTF8.GetBytes("success")).ToArray()); } catch (Exception ex) { Console.WriteLine("fw WriteBuffer" + ex.Message); socket.Send(Encoding.UTF8.GetBytes("error")); } } 这是我服务端接受处理数据流的主要代码,我的实现方式是客户端先向服务端发送一条消息介绍一下即将发送过来的文件的信息,然后服务端根据这些信息先创建一个FileStream对象并一直保存这个对象,然后客户端接着持续向服务端发送文件流数据看,服务端每接收一条文件流数据,就开始往磁盘里面写数据,直到发现已接收的数据大小和第一次客户端发过来的消息里面文件大小相同的时候,服务端就开始释放所有资源,不知道这样设计是否可行
Poopaye 2017-03-13
  • 打赏
  • 举报
回复
引用 8 楼 xiaxiaoying2012 的回复:
@shingoscar 因为文件有几十兆,还没接受完,所以服务端程序还没跑到释放资源的地方去,就卡在了1380次接受消息的地方,程序也没有报错
接收卡住那就是没数据,没数据那要么就是没发送数据,要么就是丢包了。 如果每次都1380卡住,那多半就是没发送数据。 所以检查你的客户端吧,写日志或者抓包检查
xuggzu 2017-03-13
  • 打赏
  • 举报
回复
几十兆不算大,检查你接收端保存数据是否有问题,比如,缓冲(当然,最好差不多就写盘,内存有限)或者处理逻辑是否有考虑不周的地方
xiaxiaoying2012 2017-03-13
  • 打赏
  • 举报
回复
@shingoscar 因为文件有几十兆,还没接受完,所以服务端程序还没跑到释放资源的地方去,就卡在了1380次接受消息的地方,程序也没有报错
xiaxiaoying2012 2017-03-13
  • 打赏
  • 举报
回复
@blocknum 客户端我是分块读取文件的,每次我也是从文件流中读取978个字节,然后再在这些字节前面加了46个字节作为标记,正好组成1024个字节发送到服务端的,只是发送的时候是以同步的方式发送的,之前是把客户端每次发送的数据流大小设置为102400,结果发现服务端收到的数据流和发送的不一致,所以我才改成1024个字节来发送,之前没怎么做个socket发送消息的功能,还望大神点拨一下,谢谢了
  • 打赏
  • 举报
回复
你的接收缓冲区这么小,你发送了 1380次(而且还出错),我相信即使你的程序能把大文件正确发送,你的程序也慢如蜗牛。顶多只能算是一个练习,不能算是实际产品。
  • 打赏
  • 举报
回复
我给你一个建议,然后你自己再根据测试来进行调整: 1. 接收缓冲区设置为(至少) 300k 字节。 2. 文件传送协议改为按2M一个数据块,分为两个信令,每一个信令都包括“文件相对路径、数据块偏移地址、数据块长度、发送数据内容”4部分辅助内容。第一个信令是发送 md5 校验码,对方返回校验成功或者失败。当校验失败时,你才需要(第二个信令)实际发送数据块的数据。
Poopaye 2017-03-13
  • 打赏
  • 举报
回复
8成是文件就这么大,发到最后没处理文件结束之类的 出错请贴错误,说这么多废话没用
  • 打赏
  • 举报
回复
检查你的程序的逻辑错误吧。 缓冲区不要这么小。要记住这个缓冲区是应用程序缓冲区,不是什么底层 tcp 网络传输层缓冲区,所以有人说的“tcp缓冲区1000多一点字节”跟这个并没有什么关系。你把这个缓冲区设置为300k,或者更高,往往能够得到更好的效率。 但是无论如何,都不影响首发准确性。所以你还是要首先检查自己的程序为什么“那么巧”总是在接收一定数量数据之后崩溃。应该是自己程序问题。 实际上当发送大文件时,一个比较标准的协议,应该是断点续传的,根本无需每一块数据都重新发送。例如对一个数据块进行 md5 散列计算,如果相同,就认为是无需发送,而直接跳到下一个数据块了。这样当你发送100M的数据,可能用10秒钟就发送完毕了。因为只发送有差别的那些数据块。 因此要设计一个标准协议,“分块发送数据”,不要傻傻地顺序发送数据!
xiaxiaoying2012 2017-03-13
  • 打赏
  • 举报
回复
我在服务端接收数据的时候,会做一个记录,发现只能接收1380次,你说的把每次发送的数据的大小设置大一点,也只能减少发送数据的次数吧

110,526

社区成员

发帖
与我相关
我的任务
社区描述
.NET技术 C#
社区管理员
  • C#
  • Web++
  • by_封爱
加入社区
  • 近7日
  • 近30日
  • 至今
社区公告

让您成为最强悍的C#开发者

试试用AI创作助手写篇文章吧