关于局域网文件传输的尝试(偷懒方案,嘿嘿)解决办法

关于局域网文件传输的尝试(偷懒方案,嘿嘿)
之前在开心海的帖子里( 点击访问 )看到有说这个分包机制,以及接收时的处理方式等问题的讨论,觉得逻辑上应该有懒可偷,于是就有了本文.

VB6企业版提供的WINSOCK控件本身貌似就有自动分包发送的机制-----SendData方法可以传入一个字节数组.

而SendData方法是异步的,那么传入的字节数组是怎么发送的呢?不可能是一次整个发送.

因此我猜想WINSOCK控件里面完成了如下的工作(TCP模式,UDP不知道,没试过,懒得试了....):

一,分包;

二,根据网络状态协商最佳封包大小;

三,保证发送数据的正确性.

于是就写了个简单的测试代码,看看是否与我的猜想差不多.

服务器端按多客户端的结构写的,接收到的数据按开心海的方案,分成两种处理方法.

一是直接在内存里用CopyMemory追加,接收完成后再保存至硬盘;

二是开始接收文件数据时就向硬盘保存.

最终测试,发现第二种方法在性能上要优得多.

虽然整个接收过程中代码是不断地使用PUT语句向硬盘里写数据,但是文件系统会自动进行缓冲,因此整个过程硬盘只闪了几次.

我最终的测试结果如下:

使用约44M的RAR文件(陈辉机器里找的一个什么安装包,不管它...),在陈辉机器上运行客户端,在我机器上运行服务器端,并启动服务.

网络环境是100M局域网,服务器端是INTEL双核本本+2003SP2,客户端是AMD双核台机+XPSP2,使用对联线联机.

传送过程中,峰值速度约45Mb/S,稳定速度约40Mb/S;换算为MB/S就分别约为5.6MB/S与5MB/S

100M局域网理论最高是12.5MB/S,而测试WINDOWS的文件复制,可达10MB/S(80Mb/S),不知道怎么搞的...

这里面还有个问题,就是传输过程中CPU占用严重,达到了20%到40%左右,在单核机器上应该就是40%到 80%了吧......

不过看来对于WINSOCK的猜想是正确的......因此对于一般局域网内小数据量传输,直接使用WINSOCK的机制就可以偷不少的懒了....HOHO

来看看服务器端界面:



客户端界面:



完整工程打包下载:

http://www.m5home.com/blog/article.asp?id=169

欢迎大家讨论一下,这也是个比较实际的问题.

------解决方案--------------------
我只能向老马学习了.
敬仰中....
------解决方案--------------------
不知道pplive什么的是不是这么干的
------解决方案--------------------
老马有空的话再试一下边读取边分包发送吧,比如每次读取发送64K,看看这样传输速度的峰值和CPU占用率有什么变化。
在局域网中传输时,发送端如果一次发送全部数据,winsock的确会自动分包发送,只是会造成CPU占用率高一点而已。但是如果考虑到与外网之间或者不同内网之间的传输,就又有了一个网关设备MTU的问题,比如好像大部分路由器的MTU是1400多字节,大于这个数值的包又会被再次拆分,我现在最担心的是这种情况:比如我是独立IP,给一个内网里面的机子传文件,我这边把数据很快发送过去了,在另一边由于有MTU的限制,会不会在那边的网关处造成阻塞?
------解决方案--------------------
好好学习 天天冲上
------解决方案--------------------
学习中....
------解决方案--------------------
以前搞过自己封包,效率也不错的。
------解决方案--------------------
对于TCP,在100MB的局域网当中,最好的情况应该是7~8MBytes/S.所以能达到这个速度是相当不错的.
只是CPU利用率,这是一个问题.CPU的使用分为三部分,一部分是Winsock API库以及驱动等一级占用的,这一部分占用过高的可能原因主要有几个方面:
1-a. 过小的分包,这个主要是发送方应用层主动增加与API之间的交互次数;
1-b. 过小的MTU设置,这个可以检查一下设置,有很多软件会帮你修改该设置(接收方和发送方任意一方都会产生影响);
1-c. 在没有设置MTU的情况下,最大的TCP窗口大小(接收方和发送方任意一方都会产生影响)
1). 全局HKEY_LOCAL_MACHINE\SYSTEM\CurrentControlSet\Services\Tcpip\Parameters
GlobalMaxTcpWindowSize=xx(最大为)
2). 单网卡(Per-Interface)HKEY_LOCAL_MACHINE\SYSTEM\CurrentControlSet\Services\Tcpip\Parameters\Interfaces\{[Interface UID]}
TcpWindowSize=xx
d. C只是一个全局设置或者称之为默认设置,另外对于Winsock应用层(VB的Winsock.ocx),也可以通过设置缓冲区大小:SO_RCVBUF(接收方),SO_SNDBUF(发送方)
第二部分是,Winsock应用层接口(VB所使用的Winsock.ocx),占用的,这部分占用主要受上面提到的1-a影响;
第三部分是,使用Winsocket用户应用程序,这部分占用跟编码有比较直接的关系
3-a. 影响到第一第二部分的1-a问题,这个也就是happy_sea多次提到的分包问题,这个又分为两种情况,主动分包和被动分包,被动分包,主要问题是受数据来源,或者可用缓冲内存影响.在正常的情况下,比较建议的办法是一次性senddata的数据要足够大,理论上来讲是越大越好,这样子可以尽可能减少交互次数,或者多次交互中间的间隔时间,但是当达到一定大小之后,再增大实际效果并不太大;
3-b. 使用的数据转移方法,比如楼主说的使用CopyMemory,如果一开始就分配好大小,后续接收到之后就只是CopyMemory不应该效果会比put到文件差.
------解决方案--------------------
谢谢僵哥,我一直想向僵哥请教一下我那个担心有没有必要:就是一端连续发送大量数据,而另一端有网关MTU的限制,那么会不会造成这个网关的阻塞?因为我以前那个代码(分包大小是8K)在本机和局域网中测试正常,在两个内网之间测试时经常会传输到某一进度时完全卡死,实在找不到其他原因。在我那个帖子中你提到MTU的问题后,我看了一下两个网关(路由器)的MTU都是1492。
------解决方案--------------------
当两机器不需要通过网关(中间设备)就可以直接通讯的时候,那么只需要理会此两机器的设置.不过这对于使用Winsock.ocx传输是比较被动的,只能依赖注册表等机器的设置.
------解决方案--------------------
对于传输了一定量之后中间卡住,这个时候可以使用netstat 查看一下两端的状态,看连接是否正常.通常MTU的限制,会导致一定的效率问题,但是不会影响到无法传输(TCP Window会自动调整),多半的原因是网络比较拥塞,因为MTU的限制,实际导致了设置对报文分拆,从而增加了交互的次数.但是按理说,设置了MTU,应该会使得通讯更为通畅,毕竟主机跟网关之间的网络是可以得到保障的.