zoukankan      html  css  js  c++  java
  • WCF流处理(Streaming)机制(转)

    我们首先来理解什么是Streaming流处理。

    【1】Streaming流处理的概念:

        通常情况,客户端和服务端进行交互,传递消息,都是放到接收端的缓存里,待接收完毕后再进行处理。无论接收端是客户端还是服务端都是如此。

    【1.1】要解决的问题:

         当客户端调用服务时,要阻塞客户单进程,直到消息发送完毕,服务端才开始处理数据,然后是返回处理完毕的结果给客户端,客户端接收完毕,才能解除阻塞。这 样带来的问题是当消息传递的时间很短,相对处理时间可以忽略不计,不会影响系统服务的效率。但是要是消息数据很大,比如是图片或者多媒体对象。每次传输时 间相对较大,这样接收端的等待时间过久,势必每次阻塞都会很长,进程无法继续执行。因而导致效率低下。

    【1.2】Streaming流处理:

         Streaming流处理就是WCF提供的主要针对大量消息数据处理的一种优化机制。WCF允许接收端通过通道接受消息的同时,启动对消息数据的处理,这样的过程称为流传输模型。

    【2】Streaming流处理的特点:

          显然对于处理大量的消息数据而言,流处理机制改善了系统的吞吐量和响应效率。

    【2.1】流处理操作定义:

        WCF的流处理机制需要使用.NET FrameWork定义的Stream类(它是FileStream, NetworkStream, MemoryStream 的父类)。流处理适用一下场景:

    [ServiceContract]
    interface IMyContract
    {
       [OperationContract]
       Stream StreamReply1( );

       [OperationContract]
       
    void StreamReply2(out Stream stream);

       [OperationContract]
       
    void StreamRequest(Stream stream);

       [OperationContract(IsOneWay 
    = true)]
       
    void OneWayStream(Stream stream);
    }

      它可以做为返回数据、参数、输出参数的类型。当然也可以作为单调服务的操作参数。这里使用的参数必须是可序列化的,例如MemoryStream。而FileStream不支持序列化因而不能作为参数或者返回数据的类型。

    【2.2】流处理与绑定协议:

        流处理机制在特定的绑定协议中才能使用,目前是BasicHttpBinding, NetTcpBinding, 和NetNamedPipeBinding 支持流处理模型。但是在默认情况下,WCF禁止流处理模式。

       流传输模式使用使用TransferMode进行配置,TransferMode为枚举类型,其定义如下:


        
    public enum TransferMode
        {
            
    // Summary:
            
    //     The request and response messages are both buffered.
            Buffered = 0,
            
    //
            
    // Summary:
            
    //     The request and response messages are both streamed.
            Streamed = 1,
            
    //
            
    // Summary:
            
    //     The request message is streamed and the response message is buffered.
            StreamedRequest = 2,
            
    //
            
    // Summary:
            
    //     The request message is buffered and the response message is streamed.
            StreamedResponse = 3,
        }

      只有Streamed模式支持2.1中列举的流处理模式场景。除了直接在服务上配置属性以外,我们还可以再服务的配置文件里定义流传输模式。代码如下:

          <basicHttpBinding>
            
    <binding name="basicHttpBinding"   receiveTimeout="10:10:10"  transferMode="Streamed" maxReceivedMessageSize="200000">
            
    </binding>
          
    </basicHttpBinding>
          
    <netTcpBinding>
            
    <binding name="netTcpBinding"  receiveTimeout="10:10:10" transferMode="Streamed" maxReceivedMessageSize="200000">
            
    </binding>
          
    </netTcpBinding>

       此为托管宿主的配置文件,特定的绑定协议,可以配置其传输模式。

    【2.3】注意:

        流处理在使用http协议时,其默认消息长度是64K,如果希望增加数据长度,需要在配置文件里重新设置。如: maxReceivedMessageSize="200000",具体代码如下:

    <basicHttpBinding>
            
    <binding name="basicHttpBinding"   receiveTimeout="10:10:10"  transferMode="Streamed" maxReceivedMessageSize="200000">
            
    </binding>
          
    </basicHttpBinding>

    【3】示例代码分析:

        这里测试的流处理机制,使用的是处理图片的上传于下载,分别使用Stream和其子类MemoryStream作为参数或者返回消息数据的类型。基本代码演示的是流处理三种模式场景:

    【3.1】服务端:

        服务契约分别定义了下载数据和上传数据,下载数据使用的类型MemoryStream,上传数据参数类型是是Stream。具体代码如下:

     //1.服务契约
        [ServiceContract( Namespace = "http://www.cnblogs.com/frank_xl/")]
        
    public interface IWCFService
        {
            
    //操作契约,获取数据流
            [OperationContract]
            MemoryStream DownLoadStreamData(
    string fileName);

            
    //操作契约,输出数据流
            [OperationContract]
            
    void DownLoadStreamDataOut(out MemoryStream stream, string fileName);

            
    //操作契约,上载数据流,单向操作的消息转换为数据流
            [OperationContract(IsOneWay=true)]
            
    void UpLoadStreamData(Stream stream);
        }
        
    //2.服务类,继承接口。实现服务契约定义的操作
        public class WCFService : IWCFService
        {
            
    //1实现接口定义的方法,下载文件数据流
            public MemoryStream DownLoadStreamData(string fileName)
            {
               
    // Stream stream = 
                byte[] file = new byte[200000];
                String filePath 
    = AppDomain.CurrentDomain.BaseDirectory + @"/" + fileName;
                file 
    = File.ReadAllBytes(filePath);
                MemoryStream memoryStream 
    = new MemoryStream(file);
                
    return memoryStream;
            }
            
    //2实现接口定义的方法,下载文件数据流
            public void DownLoadStreamDataOut(out MemoryStream stream, string fileName)
            {
                
    // Stream stream = 
                byte[] file = new byte[200000];
                String filePath 
    = AppDomain.CurrentDomain.BaseDirectory + @"/" + fileName;
                file 
    = File.ReadAllBytes(filePath);
                MemoryStream memoryStream 
    = new MemoryStream(file);
                stream 
    = memoryStream;
                
            }
            
    //3实现接口定义的方法,上传文件数据流
            public void UpLoadStreamData(Stream stream)
            {
                
    // codes here to deal with the stream Stream stream = 
                Console.WriteLine("The Stream length is {0}",stream.Length);

            }
        }

    【3.2】托管宿主:

        我们分别使用basicHttpBinding和netTcpBinding定义了两个服务终结点,这里不要忘记设置最大接受消息数据大小 maxReceivedMessageSize="200000",如果设置较小会导致接受数据超过设定的错误。具体代码如下:

      <system.serviceModel>
        
    <services>
          
    <service behaviorConfiguration="WCFService.WCFServiceBehavior"
            name
    ="WCFService.WCFService">
            
    <endpoint 
              address
    ="http://localhost:8002/WCFService" 
              binding
    ="basicHttpBinding" 
              contract
    ="WCFService.IWCFService">
            
    </endpoint>
            
    <endpoint
             address
    ="net.tcp://localhost:8004/WCFService"
             binding
    ="netTcpBinding"
             contract
    ="WCFService.IWCFService">
            
    </endpoint>
            
    <endpoint address="mex" binding="mexHttpBinding" contract="IMetadataExchange" />
            
    <endpoint address="mex"  binding="mexTcpBinding" contract="IMetadataExchange" />
            
    <host>
              
    <baseAddresses>
                
    <add baseAddress="http://localhost:8001/"/>
                
    <add baseAddress="net.tcp://localhost:8003/"/>
              
    </baseAddresses>
            
    </host>
          
    </service>
        
    </services>
        
    <behaviors>
          
    <serviceBehaviors>
            
    <behavior name="WCFService.WCFServiceBehavior">
              
    <serviceMetadata httpGetEnabled="true" />
              
    <serviceDebug includeExceptionDetailInFaults="false" />
            
    </behavior>
          
    </serviceBehaviors>
        
    </behaviors>
        
    <bindings>
          
    <basicHttpBinding>
            
    <binding name="basicHttpBinding"   receiveTimeout="10:10:10"  transferMode="Streamed" maxReceivedMessageSize="200000">
            
    </binding>
          
    </basicHttpBinding>
          
    <netTcpBinding>
            
    <binding name="netTcpBinding"  receiveTimeout="10:10:10" transferMode="Streamed" maxReceivedMessageSize="200000">
            
    </binding>
          
    </netTcpBinding>
        
    </bindings>
      
    </system.serviceModel>

    【3.3】客户端:

       客户端分别测试数据的上传和下载,使用不同的方法。这里的测试目前

    【4】总结:

        本文介绍了WCF流处理模型,但是实现代码出现问题。

    (1)作为WCF的流处理机制,确实为我们的大规模消息数据传输提供了理想的机制,提高了系统的效率和响应速度。

    (2)Stream作为.net类库的内部类型,在.net平台上使用来说较为方便,但是与异构平台的交互势必受到诸多限制,也违背了WCF跨平台的初衷。

    (3) 我在调试这个示例代码的过程中遇到了几个错误,基本都整理出来放到WCF分布式开发常见错误里了。使用netTcpBinding绑定进行数据传输的时 候,一个很有价值的错误就是:the socket connection was aborted. this could be caused by an error processing your message or a receive timeout being exceeded by the remote host ...这个错误我google国内和国外的一些资料,但是解决的办法都是更换协议。其实是一种很无奈的措施,目前我还没有找出更好的解决办法就是基于 netTcpBinding。表面的原因是服务处理超时。但是具体的错误信息没有这样简单。我更换协议以后其他的流服务操作调用出了问题。所以这个只能针 对特定的操作有帮助。我把这个错误收集起来供大家参考。也希望发挥大家的作用把这个问题解决。

       也许这个错误应该反映给WCF的开发小组,无论国内还是国外的技术论坛,包括MSDN都有人遇到这样的问题,而没有一个最佳的解决方案。这里我对流处理示例代码分别打包,目前都有问题。

    http://blog.csdn.net/book_frank_xl/article/details/4735907
  • 相关阅读:
    【NOIP2007】守望者的逃离
    20200321(ABC)题解 by 马鸿儒 孙晨曦
    20200320(ABC)题解 by 王一帆
    20200319(ABC)题解 by 王一帆 梁延杰 丁智辰
    20200314(ABC)题解 by 董国梁 蒋丽君 章思航
    20200309(ABC)题解 by 梁延杰
    20200307(DEF)题解 by 孙晨曦
    20200306(ABC)题解 by 孙晨曦
    20200305(DEF)题解 by 孙晨曦
    20200303(ABC)题解 by 王锐,董国梁
  • 原文地址:https://www.cnblogs.com/quietwalk/p/2133221.html
Copyright © 2011-2022 走看看