How to: Enabling Streaming

This article is now a part of the Windows SDK.

Today's post is a short article about the mechanics of enabling transport streaming. This is a complement of other articles that describe how streaming works. Like the post on transport quotas, the formatting may be a little weird because I'm pasting these in from Word and it's HTML tag soup. Update: same content, less soup.


How to: Enabling Streaming

Windows Communication Foundation (WCF) transports support two modes for transferring messages. Buffered transfers hold the entire message in a memory buffer until the transfer is complete. Streamed transfers only buffer the headers and expose the message body as a stream, from which smaller portions can be read at a time. Streamed transfers can improve the scalability of a service by eliminating the need for large memory buffers. Whether changing the transfer mode will improve scalability depends on the size of the messages being transferred. Large message sizes favor using streamed transfers.

By default, the HTTP, TCP/IP and named pipe transports use buffered transfers. This document describes how to switch these transports from a buffered to streamed transfer mode and the consequences of doing so.

Enabling Streamed Transfers

Selecting between buffered and streamed transfer modes is done on the binding element of the transport. The binding element has a TransferMode property that can be set to Buffered, Streamed, StreamedRequest, or StreamedResponse. Setting the transfer mode to Streamed enables streaming communication in both directions. Setting the transfer mode to StreamedRequest or StreamedResponse enables streaming communication in the indicated direction only.

The BasicHTTPBinding exposes the TransferMode property on the binding. For other transports, you will need to create a custom binding to set the transfer mode.

The following code snippet shows setting the TransferMode property to streaming through code:

 TcpTransportBindingElement transport = new TcpTransportBindingElement();
transport.TransferMode = TransferMode.Streamed;
BinaryMessageEncodingBindingElement encoder = new BinaryMessageEncodingBindingElement();
CustomBinding binding = new CustomBinding(encoder, transport);

The following code snippet shows setting the TransferMode property to streaming through configuration:

 <customBinding>
   <binding name="streamingBinding">
      <binaryMessageEncoding />
      <tcpTransport transferMode=”Streamed” />
   </binding>
</customBinding>

The decision to use either buffered or streamed transfers is a local decision of the endpoint. For HTTP transports, the transfer mode does not propagate across a connection, or to proxy servers and other intermediaries. Setting the transfer mode is not reflected in the description of the service interface. After generating a proxy to a service, you will need to edit the configuration file for services intended to be used with streamed transfers to set the mode. For TCP and named pipe transports, the transfer mode is propagated as a policy assertion.

Restrictions of Streamed Transfers

Using the streamed transfer mode causes the runtime to enforce additional restrictions.

  • Operations that occur across a streamed transport can have a contract with at most one input and/or one output parameter. That parameter corresponds to the entire body of the message and must be a Message, be a subtype of System.IO.Stream, or implement IXmlSerializable. Having a return value for an operation is equivalent to having an output parameter.
  • Some WCF features such as Reliable Messaging, Transactions, and SOAP message-level security rely on buffering messages for transmissions. Using these features may reduce or eliminate the performance benefits gained by using streaming. To secure a streamed transport, use transport level security only or use transport level security plus authentication-only message security. Mixed-mode security, which combines WS-Security claims with transport security, can be used with streaming.
  • SOAP headers are always buffered, even when the transfer mode is set to streamed. The headers for a message must not exceed the size of the MaxBufferSize transport quota. The documentation for transport quotas further describes this setting.

Differences Between Buffered and Streamed Transfers

Changing the transfer mode from buffered to streamed also changes the native channel shape of the TCP and named pipe transports. For buffered transfers, the native channel shape is IDuplexSessionChannel. For streamed transfers, the native channels are IRequestChannel and IReplyChannel. This means that sessionful service contracts do not compose with transport streaming.


Next time: Five Pitfalls of the Channel Model, Part 1