首页 新闻 会员 周边

(现金酬谢)wcf 广域网传文件稳定性问题

0
悬赏园豆:50 [已解决问题] 解决于 2013-01-06 08:24

我用WCF做了一个服务端和客户端传输文件的软件,现在有个问题就是有时传输会出现速度为0,一会儿又会速度很快,非常不稳定,用QQ传即使网速慢,它也不会出一为0的情况,我传输时已经将文件分的很小了16kb,用5个线程进行上传,我建的是需要有回应的上传方法!!

 

下面是传输用到的方法接口!!

 

请高手帮个助,可以现金酬谢!!

 

可以QQ联系:63729204

 

    [ServiceContract(SessionMode = SessionMode.Required)]
    public interface IUpload
    {
        /// <summary>
        /// 上传方法
        /// </summary>
        /// <param name="userName">软件用户名</param>
        /// <param name="fileName">上传的文件名</param>
        /// <param name="begin"></param>
        /// <param name="len"></param>
        /// <param name="data"></param>
        //[OperationContract(IsOneWay = true)]
        [OperationContract]
        void UploadFileByByte(string userName, string taskName, string fileName, long begin, long len, byte[] data);

        //上传完成后需要验证是否正确
        //remark则是任务的说明,如果检证成功,解压后将说明一写成TXT文档一起放到解压后的目录
        [OperationContract]
        bool Invalidate(string userName, string taskName, string fileName, string remark, string md5Code, out string errmsg);
    }
问题补充:

用STREAM的话,好像只能用单线程,才好实现断点续传!!这样对速度不知道有没有影响,

还有就是用STREAM的话,怎么得到上传的速度和进度呢?

Code Machine的主页 Code Machine | 初学一级 | 园豆:73
提问于:2012-12-11 12:26
< >
分享
最佳答案
0

你把传输模式改成 Stream。

收获园豆:50
Launcher | 高人七级 |园豆:45045 | 2012-12-11 13:09

stream的话就需要封装了,我先试试效果吧,用STREAM

Code Machine | 园豆:73 (初学一级) | 2012-12-11 13:28

用stream的话,不方便实现断点续传,我不清楚有没有传完,专到什么地方了?也不方便实现多线程上传吧!多线程和断点续传这二方面的问题!

Code Machine | 园豆:73 (初学一级) | 2012-12-11 14:10

@Code Machine: 的确是有办法实现多线程断点续传。多线程断点续传的要点是:

1,先将文件的大小发送给服务器,服务器根据此大小创建一个空的文件;

2,客户端启用多个线程,每个线程被分配从本地文件的某一段开始读取数据并上传;

3,服务器根据收到的数据段号来写入文件的不同部分;

Launcher | 园豆:45045 (高人七级) | 2012-12-11 14:25

@Launcher: 

1、用byte和用stream进行传输在速度上没有区别呢?

2、byte方式到底是怎么在网络中传输的,比如byte包的大小是1024kb,是整个一起传么?

3、stream方式到底是怎么在网络中传输的,比如还是有一个1024kb大小的stream,系统会自动根据现在网速的快慢一点一点(像蚂蚁搬家)方式传么?

4、用stream方式的话,如果我将大文件分成小块一点一点的传输,这样对性能是不是有影响,因为每一调用上传,在服务端都会实例话一个新对像!

谢谢

Code Machine | 园豆:73 (初学一级) | 2012-12-11 14:38

@Code Machine: 其实在WCF中应该是Buffer和Stream的区别。我们抛开TCP这一层,从WCF的概念上来讲,Buffer模式是指一次性提交完整个Buffer;Stream模式是则可以分多次部分提交完整个Buffer。结合TCP来说,Buffer模式提交完整个Buffer后,TCP层才开始发起传输,通常的传输包大小MTU为1492(Windows默认为1500,根据路由节点的设置,实际的MTU值会有所调整,以达到最大化利用带宽);对于Stream模式来说,每次写入,TCP层就会将新写入的数据发送出去,传输包大小不受Buffer或Stream模式影响。

你必须理解网络七层协议,WCF工作在应用层,具体的数据如何组包,如何重传,是有TCP/IP协议栈控制的,在这一层,每发送完一个MTU,客户端会得到一个应答(ACK) 包,然后通过一定的算法检测,客户端会决定是重新发送,还是继续传下一个包。因此网速影响的是RTT(往返时间)的值,也就是客户端送一个不大于MTU的包开始到客户端接收到服务器对该包的应答包的时间。

那么从WCF上来说,为了在RTT较大或丢包较多时能够保证持续发送数据,通常需要设置较大的SendTimeout和RecivedTimeout的值,可能还需要设置inactivityTimeout(如果设置了可靠会话),当然可能还有些其它的Timeout你可以自己查资料看下。那么这里的Timeout和TCP/IP协议栈的Timeout是有差别的,前者是后者的累计值。此处就体现出Buffer和Stream的差异了,Buffer是整体提交,而Stream是分段提交,因此Timeout的要求上,对于相同的大小的数据,前者会比后者大。

如果觉得实例化一个新的对象影响性能,你可以将服务设置为Singleton,并发模式设置为Multiple,不使用同步上下文,当然涉及到安全、会话、可靠会话的话,设置还有些不同。当然,一般来说,只要你的服务对象不重,PerCall并不会占用过多的资源,同时我们也可以使用资源池模式来服用已经创建的服务对象(类似数据库连接池)。

Launcher | 园豆:45045 (高人七级) | 2012-12-11 15:17

@Launcher: 这段话看了四五遍,很受用,谢谢,还有一个问题 ,能不能得到TCP上单位时间内发送MTU的大小,我想得到网速,最好是本软件的网速,而不是整个网络的网速!找了半天了也没有找到相关的内容!

Code Machine | 园豆:73 (初学一级) | 2012-12-11 15:46

@Launcher: 还补充一个问题 ,就是TransferMode中的这几个的区别是什么???   
        //     对请求和响应消息进行流式处理。
        Streamed = 1,
        //
        // 摘要:
        //     对请求消息进行流式处理,对响应消息进行缓冲处理。
        StreamedRequest = 2,
        //
        // 摘要:
        //     对请求消息进行缓冲处理,对响应消息进行流式处理。
        StreamedResponse = 3,

Code Machine | 园豆:73 (初学一级) | 2012-12-11 15:58

@Code Machine: 你只能抓包实现,好像是在XP sp3之前的操作系统上可以使用 RAW SOCKET来抓包,除此之外你就只能使用驱动来抓包了,比如 WinPcap(开源的)。通常来说除非你使用SOCKET来实现自定义协议,一般不需要知道MTU的值。

如果你只是想知道你的应用程序的实际传输速率,你可以使用我开始提到的通过抓包的形式来做分析。另外你也可以通过"资源监视器"中的“网络”来得到你的进程的网络参数。

再次,你可以在你的代码中直接统计。

Launcher | 园豆:45045 (高人七级) | 2012-12-11 16:03

@Code Machine: MSDN上已经很好的解释了,我说下用处吧,Buffer常用来处理较小体积的数据,速度快,占用资源少,而 Stream 通常用来处理体积较大的数据,数据较大时,如果采用 Buffer 模式,会占用过多的内存资源,因此:

StreamedRequest:对于服务端来说,用以接收较大的数据;

StreamedResponse:对于服务端来说,用以返回给客户端较大的数据。

Launcher | 园豆:45045 (高人七级) | 2012-12-11 16:13

@Launcher: 根据我的实际测试结果来看,wcf的tcp绑定使用Stream模式传输文件时,每次传输的字节数与MTU无关,而是与TCP的窗口大小有关(根据观察而猜测的),根据默认设置一般在4096(有时为4089),调整maxBytesPerRead属性最大支持65535,这也是未使用TCP窗口扩大选项时所能支持的每次传输的最大字节数65535(实际最大得到了65535+7),此时在不考虑其他因素情况下,传输速度最快。

楼主提到的获取当前应用程序的网速问题,属于应用层的事情,可以自己处理,根据收到的字节数和已花的时间,自己根据需要去算实时速率和平均速率,这样是最准确的。

下面是我前不久测试时做的记录:

测试wcf的http和tcp绑定以及非wcf的命名管道传输文件速度对比”和”关于wcf的tcp绑定传文件的速率问题的深究

Tony二师弟 | 园豆:204 (菜鸟二级) | 2013-03-15 20:46

@Launcher: 根据我的实际测试结果来看,wcf的tcp绑定使用Stream模式传输文件时,每次传输的字节数与MTU无关,而是与TCP的窗口大小有关(根据观察而猜测的),根据默认设置一般在4096(有时为4089),调整maxBytesPerRead属性最大支持65535,这也是未使用TCP窗口扩大选项时所能支持的每次传输的最大字节数65535(实际最大得到了65535+7),此时在不考虑其他因素情况下,传输速度最快。

楼主提到的获取当前应用程序的网速问题,属于应用层的事情,可以自己处理,根据收到的字节数和已花的时间,自己根据需要去算实时速率和平均速率,这样是最准确的。

下面是我前不久测试时做的记录:

测试wcf的http和tcp绑定以及非wcf的命名管道传输文件速度对比”和”关于wcf的tcp绑定传文件的速率问题的深究

Tony二师弟 | 园豆:204 (菜鸟二级) | 2013-03-15 20:49
其他回答(1)
0

我之前也用 WCF 实现过文件上传,传输的方式是用默认那种,可以实现断点功能。

WCF 每次最大传输数据量为2M,而你的只使用了默认的16K,实在是太慢了。

你那种多线程是同时传一个文件,还是传多个文件。另外建议你用 异步的方式来调用 WCF。其实用线程没什么好处,因为网速是平均分配,而且线程用多了,性能也会有影响。虽然文件可以多线程的读取,但写入只能是单个线程。

最后调用非托管代码要比较谨慎,要考虑到网络,硬盘空间,文件只读等问题。

geass.. | 园豆:1821 (小虾三级) | 2012-12-11 19:49
清除回答草稿
   您需要登录以后才能回答,未注册用户请先注册