user-0 提问: SOCKET 传输大文件应该怎么做？

回复:
user: user-0
content: 谢谢各位大牛的回答，因为最近有事，所以结贴晚了，小弟拜谢！ 另外：代码已经实现了，速度也能达到70+！

user: user-1
content: 在文件大小相同的前提下：  读刚读过的文件比头次读没读过的文件快  读转速快的硬盘上的文件比读转速慢的硬盘上的文件快  读没有磁盘碎片的文件比读有磁盘碎片的文件快  读文件不处理比边读边处理快  单线程从头到尾一次读文件比多线程分别读文件各部分快（非固态硬盘上）  读固态硬盘上的文件比读普通硬盘上的文件快

user: user-2
content: 引用 20 楼 mujiok2003 的回复:[quote=引用 17 楼 u013093541 的回复:] [quote=引用 13 楼 mujiok2003 的回复:] 个人觉得单线程non-blocking IO+ synchronous I/O multiplexing(select/poll/epoll...) 更好。  牛哥，能说仔细下么？ [/quote]  其实没有必要弄搞那么复杂，直接用send/recv就好了， 只要网络足够通畅， 轻松达到。 我在我的笔记本(10Gbps的网卡）上轻松上90MB/s。 [/quote]  上图：

user: user-2
content: 引用 17 楼 u013093541 的回复:[quote=引用 13 楼 mujiok2003 的回复:] 个人觉得单线程non-blocking IO+ synchronous I/O multiplexing(select/poll/epoll...) 更好。  牛哥，能说仔细下么？ [/quote]  其实没有必要弄搞那么复杂，直接用send/recv就好了， 只要网络足够通畅， 轻松达到。 我在我的笔记本(10Gbps的网卡）上轻松上90MB/s。

user: user-2
content: 个人觉得单线程non-blocking IO+ synchronous I/O multiplexing(select/poll/epoll...) 更好。

user: user-2
content: 引用 11 楼 u013093541 的回复:昨天有去做测试，发现，并不是IO的问题造成整体的传输慢！还会代码存在问题 我按照自己3的思路去完成代码，也就是在Server端，我分了两个线程，一个线程用于读取文件，并将读到的buf加入到一个动态链表尾部，另一个线程从此链表头取数据，进行send操作，并且对send的返回值进行校验，如果send的返回值和预期的发送字节数不同，则采用断点重传的方式，继续传输。在Client端口，也是用类似的服务端的机制，维护一个链表，进行读取。 需要说明的是：我维护的这个链表是由深度的，并通过深度来调节两个线程对链表的操作。  这个思路是可行的的， 注意两个问题： 1. 防止文件IO过快， 导致你的队列(链表）迅速膨胀。 2. 队列(或链表）要有同步机制， 尽量减小临界区。

user: user-0
content: 昨天有去做测试，发现，并不是IO的问题造成整体的传输慢！还会代码存在问题 我按照自己3的思路去完成代码，也就是在Server端，我分了两个线程，一个线程用于读取文件，并将读到的buf加入到一个动态链表尾部，另一个线程从此链表头取数据，进行send操作，并且对send的返回值进行校验，如果send的返回值和预期的发送字节数不同，则采用断点重传的方式，继续传输。在Client端口，也是用类似的服务端的机制，维护一个链表，进行读取。 需要说明的是：我维护的这个链表是由深度的，并通过深度来调节两个线程对链表的操作。

user: user-3
content: 每秒50M能达到预期效果吗？ 有结果回复下

user: user-1
content: 引用 16 楼 u013093541 的回复:[quote=引用 14 楼 zhao4zhong1 的回复:] 在文件大小相同的前提下：  读刚读过的文件比头次读没读过的文件快  读转速快的硬盘上的文件比读转速慢的硬盘上的文件快  读没有磁盘碎片的文件比读有磁盘碎片的文件快  读文件不处理比边读边处理快  单线程从头到尾一次读文件比多线程分别读文件各部分快（非固态硬盘上）  读固态硬盘上的文件比读普通硬盘上的文件快  赵老师，您说的这句“ 单线程从头到尾一次读文件比多线程分别读文件各部分快（非固态硬盘上）”只是针对的读取文件是么？那在我传输的过程中，采用多线程应该是比单线程传输要快一些吧？ 谢谢指教！[/quote] 是的。

user: user-0
content: 引用 13 楼 mujiok2003 的回复:个人觉得单线程non-blocking IO+ synchronous I/O multiplexing(select/poll/epoll...) 更好。  牛哥，能说仔细下么？

user: user-0
content: 引用 14 楼 zhao4zhong1 的回复:在文件大小相同的前提下：  读刚读过的文件比头次读没读过的文件快  读转速快的硬盘上的文件比读转速慢的硬盘上的文件快  读没有磁盘碎片的文件比读有磁盘碎片的文件快  读文件不处理比边读边处理快  单线程从头到尾一次读文件比多线程分别读文件各部分快（非固态硬盘上）  读固态硬盘上的文件比读普通硬盘上的文件快  赵老师，您说的这句“ 单线程从头到尾一次读文件比多线程分别读文件各部分快（非固态硬盘上）”只是针对的读取文件是么？那在我传输的过程中，采用多线程应该是比单线程传输要快一些吧？ 谢谢指教！

user: user-0
content: 引用 12 楼 mujiok2003 的回复:[quote=引用 11 楼 u013093541 的回复:] 昨天有去做测试，发现，并不是IO的问题造成整体的传输慢！还会代码存在问题 我按照自己3的思路去完成代码，也就是在Server端，我分了两个线程，一个线程用于读取文件，并将读到的buf加入到一个动态链表尾部，另一个线程从此链表头取数据，进行send操作，并且对send的返回值进行校验，如果send的返回值和预期的发送字节数不同，则采用断点重传的方式，继续传输。在Client端口，也是用类似的服务端的机制，维护一个链表，进行读取。 需要说明的是：我维护的这个链表是由深度的，并通过深度来调节两个线程对链表的操作。  这个思路是可行的的， 注意两个问题： 1. 防止文件IO过快， 导致你的队列(链表）迅速膨胀。 2. 队列(或链表）要有同步机制， 尽量减小临界区。 [/quote]  小弟想请问一下，我现在维护一个链表，确实会使得链表的长度在某一个时刻徒增，那么应该如何设置链表的深度（文件200M）同时，发送的块大小是要一个一个的试？还是怎样才能或得更好的传输速度？ 第二个问题，您说的同步机制，我理解，但是说减小临界区是什么意思？是说对临界数据的选择尽量使得其数据量小么？ 谢谢！

user: user-4
content: 引用 4 楼 zhao4zhong1 的回复:不知道有多少前人掉在TCP Socket send(人多)send(病少)send(财富) recv(人多病)recv(少财富) 陷阱里面啊！ http://bbs.csdn.net/topics/380167545好熟悉的回复，我以前发帖子你也是这样的回复

user: user-2
content: 引用 1 楼 zilaishuichina 的回复:文件切块，是没有错的。发送端接受端开缓存，也是没有错的  至于lz说的速度慢，可能不是慢在网络IO上： 1：可能是慢在磁盘IO上，也就是你文件内容可能是一边读一边发的，lz可以尝试把文件内容全部读入内存，然后直接对内存中的文件数据分块发送。或者lz可以先做下测试，把你读取文件的代码先去掉，直接malloc分配50M，随便填点数据，然后发送这块内存。如果不慢了，证明是读文件的问题。如果还慢，只能说是你网络代码效率的问题了，比如可以选择换用IOCP模型在做尝试 2：可能是慢在频繁的申请释放内存上，lz可以考虑使用内存池，给你提供的这个内存池你可以看最后的测试效果，效率相差2个数量级 文件IO速度一般比socket IO快，试试scatter read, gather write, 目的是减少系统调用次数。

user: user-2
content: 引用出现1的问题，是因为发端太快，造成丢包  TCP不会丢包。

user: user-5
content: 引用 6 楼 u013093541 的回复:谢谢，各位大牛，小弟现在就去改代码，今天加个班，明天再向各位求教！ 解决问题要紧，先别关IOCP一类的了，不然干完需要一段时间了

user: user-0
content: 谢谢，各位大牛，小弟现在就去改代码，今天加个班，明天再向各位求教！

user: user-1
content: 超过2GB的文件可能需要用到_lseeki64函数。

user: user-1
content: 不知道有多少前人掉在TCP Socket send(人多)send(病少)send(财富) recv(人多病)recv(少财富) 陷阱里面啊！ http://bbs.csdn.net/topics/380167545

user: user-5
content: 千兆网卡直接send recv 应该也不会出问题吧，而且速度也应该不会慢，是不是你忘了处理粘包的问题呢？ 楼上说的文件分块传输也是可以考虑的，通过多线程发送，接收完毕之后再将文件合并， IOCP有一个transmitfile 你可以试一下 希望可以帮到你