`
cloudtech
  • 浏览: 4612432 次
  • 性别: Icon_minigender_1
  • 来自: 武汉
文章分类
社区版块
存档分类
最新评论

wcf传输模式-流模式(Streaming)

 
阅读更多

Windows Communication Foundation (WCF) can send messages using either buffered or streamed transfers. In the default buffered-transfer mode, a message must be completely delivered before a receiver can read it. In streaming transfer mode, the receiver can begin to process the message before it is completely delivered. The streaming mode is useful when the information that is passed is lengthy and can be processed serially. Streaming mode is also useful when the message is too large to be entirely buffered.

To enable streaming, define the OperationContract appropriately and enable streaming at the transport level.

To stream data

  1. To stream data, the OperationContract for the service must satisfy two requirements:

    1. The parameter that holds the data to be streamed must be the only parameter in the method. For example, if the input message is the one to be streamed, the operation must have exactly one input parameter. Similarly, if the output message is to be streamed, the operation must have either exactly one output parameter or a return value.
    2. At least one of the types of the parameter and return value must be either Stream, Message, or IXmlSerializable.

    The following is an example of a contract for streamed data.

  2. (Namespace = "http://Microsoft.ServiceModel.Samples")]
    public interface IStreamingSample
    {
    [OperationContract]
    Stream GetStream(string data);
    [OperationContract]
    bool UploadStream(Stream stream);
    [OperationContract]
    Stream EchoStream(Stream stream);
    [OperationContract]
    Stream GetReversedStream();

    }

    The GetStream operation receives some buffered input data as a string, which is buffered, and returns a Stream, which is streamed. Conversely UploadStream takes in a Stream (streamed) and returns a bool (buffered). EchoStream takes and returns Stream and is an example of an operation whose input and output messages are both streamed. Finally, GetReversedStream takes no inputs and returns a Stream (streamed).

  3. Streaming must be enabled on the binding. You set a TransferMode property, which can take one of the following values:

    1. Buffered,
    2. Streamed, which enables streaming communication in both directions.
    3. StreamedRequest, which enables streaming the request only.
    4. StreamedResponse, which enables streaming the response only.

    The BasicHttpBinding exposes the TransferMode property on the binding, as does NetTcpBinding and NetNamedPipeBinding. The TransferMode property can also be set on the transport binding element and used in a custom binding.

    The following samples show how to set TransferMode by code and by changing the configuration file. The samples also both set the maxReceivedMessageSize property to 64 MB, which places a cap on the maximum allowable size of messages on receive. The default maxReceivedMessageSize is 64 KB, which is usually too low for streaming scenarios. Set this quota setting as appropriate depending on the maximum size of messages your application expects to receive. Also note that maxBufferSize controls the maximum size that is buffered, and set it appropriately.

    1. The following configuration snippet from the sample shows setting the TransferMode property to streaming on the basicHttpBinding and a custom HTTP binding.

      <basicHttpBinding>
      <binding name="HttpStreaming" maxReceivedMessageSize="67108864"
      transferMode="Streamed"/>
      </basicHttpBinding>
      <!-- an example customBinding using Http and streaming-->
      <customBinding>
      <binding name="Soap12">
      <textMessageEncoding messageVersion="Soap12WSAddressing10" />
      <httpTransport transferMode="Streamed" maxReceivedMessageSize="67108864"/>
      </binding>
      </customBinding>
    2. The following code snippet shows setting the TransferMode property to streaming on the basicHttpBinding and a custom HTTP binding.
      public static Binding CreateStreamingBinding()
      {
      BasicHttpBinding b = new BasicHttpBinding();
      b.TransferMode = TransferMode.Streamed;
      return b;
      }
    3. The following code snippet shows setting the TransferMode property to streaming on a custom TCP binding.

      public static Binding CreateStreamingBinding()
      {
      TcpTransportBindingElement transport = new TcpTransportBindingElement();
      transport.TransferMode = TransferMode.Streamed;
      BinaryMessageEncodingBindingElement encoder = new BinaryMessageEncodingBindingElement();
      CustomBinding binding = new CustomBinding(encoder, transport);
      return binding;
      }
  4. The operations GetStream, UploadStream, and EchoStream all deal with sending data directly from a file or saving received data directly to a file. The following code is for GetStream.

    public Stream GetStream(string data)
    {
    //this file path assumes the image is in
    // the Service folder and the service is executing
    // in service/bin
    string filePath = Path.Combine(
    System.Environment.CurrentDirectory,
    ".//..//image.jpg");
    //open the file, this could throw an exception
    //(e.g. if the file is not found)
    //having includeExceptionDetailInFaults="True" in config
    // would cause this exception to be returned to the client
    try
    {
    FileStream imageFile = File.OpenRead(filePath);
    return imageFile;
    }
    catch (IOException ex)
    {
    Console.WriteLine(
    String.Format("An exception was thrown while trying to open file {0}", filePath));
    Console.WriteLine("Exception is: ");
    Console.WriteLine(ex.ToString());
    throw ex;
    }
    }

Writing a custom stream

  1. To do special processing on each chunk of a data stream as it is being sent or received, derive a custom stream class from Stream. As an example of a custom stream, the following code contains a GetReversedStream method and a ReverseStream class-.

    GetReversedStream creates and returns a new instance of ReverseStream. The actual processing happens as the system reads from the ReverseStream object. The ReverseStream.Read method reads a chunk of bytes from the underlying file, reverses them, then returns the reversed bytes. This method does not reverse the entire file content; it reverses one chunk of bytes at a time. This example shows how you can perform stream processing as the content is being read to or written from the stream.

    class ReverseStream : Stream
    {

    FileStream inStream;
    internal ReverseStream(string filePath)
    {
    //opens the file and places a StreamReader around it
    inStream = File.OpenRead(filePath);
    }
    public override bool CanRead
    {
    get { return inStream.CanRead; }
    }

    public override bool CanSeek
    {
    get { return false; }
    }

    public override bool CanWrite
    {
    get { return false; }
    }

    public override void Flush()
    {
    throw new Exception("This stream does not support writing.");
    }

    public override long Length
    {
    get { throw new Exception("This stream does not support the Length property."); }
    }

    public override long Position
    {
    get
    {
    return inStream.Position;
    }
    set
    {
    throw new Exception("This stream does not support setting the Position property.");
    }
    }

    public override int Read(byte[] buffer, int offset, int count)
    {
    int countRead = inStream.Read(buffer, offset, count);
    ReverseBuffer(buffer, offset, countRead);
    return countRead;
    }

    public override long Seek(long offset, SeekOrigin origin)
    {
    throw new Exception("This stream does not support seeking.");
    }

    public override void SetLength(long value)
    {
    throw new Exception("This stream does not support setting the Length.");
    }

    public override void Write(byte[] buffer, int offset, int count)
    {
    throw new Exception("This stream does not support writing.");
    }
    public override void Close()
    {
    inStream.Close();
    base.Close();
    }
    protected override void Dispose(bool disposing)
    {
    inStream.Dispose();
    base.Dispose(disposing);
    }
    void ReverseBuffer(byte[] buffer, int offset, int count)
    {

    int i, j;

    for (i = offset, j = offset + count - 1; i < j; i++, j--)
    {
    byte currenti = buffer[i];
    buffer[i] = buffer[j];
    buffer[j] = currenti;
    }

    }
    }

    来自MSDN:How to: Enable Streaming
  2. 中文版:

    Windows Communication Foundation (WCF) 可以使用缓冲传输或流传输来发送消息。在默认的缓冲传输模式中,只有在一条消息全部传递完之后,接收方才能读取该消息。在流传输模式中,不必等到消息全部传递完,接收方便可以开始处理该消息。当传递的信息很长且可以依次处理时,流模式非常有用。当消息太长以至于无法全部缓冲时,流模式也非常有用。

    若要启用流处理,请适当地定义OperationContract并在传输级别上启用流处理。

    对数据进行流处理

    1. 若要对数据进行流处理,服务的OperationContract必须满足两个要求:

      1. 保留要进行流处理的数据的参数必须是方法中的唯一参数。例如,如果要对输入消息进行流处理,则该操作必须正好具有一个输入参数。同样,如果要对输出消息进行流处理,则该操作必须正好具有一个输出参数或一个返回值。
      2. 参数和返回值的类型中至少有一个必须是Stream,MessageIXmlSerializable

      下面是流处理数据的协定的示例。

      GetStream操作接收一些缓冲输入数据作为经过缓冲的string,并返回经过流处理的Stream。相反,UploadStream接收一个经过流处理的Stream,并返回一个经过缓冲的boolEchoStream接收并返回Stream,是一个其输入和输出消息都经过流处理的操作的示例。最后,GetReversedStream不接收输入,将返回经过流处理的Stream

    2. 必须在绑定上启用流处理。设置TransferMode属性,可以采用下面的值之一:

      1. Buffered,
      2. Streamed,此值在两个方向上启用流通信。
      3. StreamedRequest,此值仅启用请求流处理。
      4. StreamedResponse,此值仅启用响应流处理。

      BasicHttpBinding公开绑定上的TransferMode属性,与NetTcpBindingNetNamedPipeBinding一样。还可以在传输绑定元素上设置TransferMode属性,并且在自定义绑定中使用。

      下面的示例演示如何通过代码和通过更改配置文件来设置TransferMode。两个示例都将maxReceivedMessageSize属性设置为 64 MB,这是可以接收的最大消息大小。默认的maxReceivedMessageSize是 64 KB,对于流处理方案而言,此值通常太低。根据应用程序期望接收的消息的最大大小适当地设置此配额设置。还请注意,maxBufferSize可控制缓冲的最大大小,应适当地进行设置。

      1. 下面示例中的配置段演示如何将basicHttpBinding和自定义 HTTP 绑定上的TransferMode属性设置为流处理。
      2. 下面的代码段演示如何将basicHttpBinding和自定义 HTTP 绑定上的TransferMode属性设置为流处理。
      3. 下面的代码段演示如何将自定义 TCP 绑定上的TransferMode属性设置为流处理。
    3. GetStreamUploadStreamEchoStream操作都可以处理直接从文件发送数据或将接收的数据直接保存到文件的情况。下面的代码适用于GetStream

    编写自定义流

    1. 若要在发送或接收数据流的每个块区时对其进行特殊处理,可从Stream派生一个自定义流类。与自定义流的示例一样,下面的代码包含GetReversedStream方法和ReverseStream类。

      GetReversedStream创建并返回一个新的ReverseStream实例。当系统从ReverseStream对象中读取时,发生实际处理。ReverseStream.Read方法从基础文件中读取字节块区,反转字节,然后返回反转的字节。此方法不会反转整个文件内容;一次只能反转一个字节块区。本示例演��在从流中读取内容或将内容写入到流中时如何执行流处理

分享到:
评论

相关推荐

Global site tag (gtag.js) - Google Analytics