Streaming

By default, when the client and the service exchange messages, these messages are buffered on the receiving end and delivered only once the entire message has been received. This is true whether it is the client sending a message to the service or the service returning a message to the client. As a result, when the client calls the service, the service is invoked only after the client's message has been received in its entirety; likewise, the client is unblocked only once the returned message with the results of the invocation has been received in its entirety.

For sufficiently small messages, this exchange pattern provides for a simple programming model because the latency caused by receiving the message is usually negligible compared with the message processing itself. However, when it comes to much larger messages—such as ones involving multimedia content, large files, or batches of data—blocking until the entire message has been received may be impractical. To handle such cases, WCF enables the receiving side (be it the client or the service) to start processing the data in the message while the message is still being received by the channel. This type of processing is known as streaming transfer mode. With large payloads, streaming provides improved throughput and responsiveness because neither the receiving nor the sending side is blocked while the message is being sent or received.

I/O Streams

For message streaming, WCF requires the use of the .NET Stream class. In fact, the contract operations used for streaming look just like conventional I/O methods. The Stream class is the base class of all the I/O streams in .NET (such as the FileStream, NetworkStream, and MemoryStream classes), allowing you to stream content from any of these I/O sources. All you need to do is return or receive a Stream as an operation parameter, as shown in Example 5-17.

Example 5-17. Streaming operations

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

   [OperationContract]
   void StreamReply2(out Stream stream);

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

Note that you can only define as an operation parameter the abstract class Stream or a specific serializable subclass such as MemoryStream. Subclasses such as FileStream are not serializable; you will have to use the base Stream instead.

WCF lets services stream the reply, the request, or both the request and the reply.

Streaming and Binding

Only the TCP, IPC, and basic HTTP bindings support streaming. With all of these bindings streaming is disabled by default, and the binding will buffer the message in its entirety even when a Stream is used. You have to enable streaming by setting the TransferMode property according to the desired streaming mode. For example, when using the BasicHttpBinding:

public enum TransferMode
{
   Buffered, //Default
   Streamed,
   StreamedRequest,
   StreamedResponse
}
public class BasicHttpBinding : Binding,...
{
   public TransferMode TransferMode
   {get;set;}
   //More members
}

TransferMode.Streamed supports all streaming modes, and this is the only transfer mode that can support all the operations in Example 5-17. However, if the contract contains only a specific type of streaming, such as streamed reply:

[ServiceContract]
interface IMyContract
{
   //Stream reply
   [OperationContract]
   Stream GetStream1( );

   [OperationContract]
   int MyMethod( );
}

you can have a buffered request and streamed reply by selecting TransferMode.StreamedResponse.

You will need to configure the binding on the client or service side (or both) per the required stream mode:

<configuration>
   <system.serviceModel>
      <client>
         <endpoint
            binding = "basicHttpBinding"
            bindingConfiguration = "StreamedHTTP"
            ...
         />
      </client>
      <bindings>
         <basicHttpBinding>
            <binding name = "StreamedHTTP"
               transferMode = "Streamed"
            />
         </basicHttpBinding>
      </bindings>
   </system.serviceModel>
</configuration>

Streaming and Transport

It is important to realize that WCF streaming is merely a programming model nicety. The underlying transport itself is not streamed, and the default maximum message size is set to 64K. This may be a problem with the sort of data you are likely to use streaming with, because streamed messages tend to be very large (hence the motivation for streaming in the first place). If the default limit proves insufficient, you can increase the maximum message size on the receiving side by setting the MaxReceivedMessageSize property to the expected maximum message size:

public class BasicHttpBinding : Binding,...
{
   public long MaxReceivedMessageSize
   {get;set;}
   //More memebrs
}

You can even use trial-and-error at runtime to find out what the streamed message size is and set the binding accordingly.

Typically, though, you would place that piece of configuration in the config file and avoid doing it programmatically, as message size tends to be deployment-specific:

<bindings>
   <basicHttpBinding>
      <binding name = "StreamedHTTP"
         transferMode = "Streamed"
         maxReceivedMessageSize = "120000"
      />
   </basicHttpBinding>
</bindings>

Stream Management

When a client passes a request stream to a service, the service may read from the stream long after the client is gone. The client has no way of knowing when the service is done using the stream, and consequently should not close the stream itself. WCF will automatically close the client-side stream once the service is done using it.

A similar problem exists when a client interacts with a response stream: the stream is produced on the service side, but the service should not close it because it has no way of knowing when the client is done using the stream. In this case, WCF can't help, because it has no idea what the client is doing with the stream. The client is therefore always responsible for closing reply streams.

Tip

When you use streaming, you cannot use message-level transfer security. This is the main reason why only the TCP, IPC, and basic bindings (and their subclasses) support streaming: with these bindings, you typically do not (and, in the case of IPC, cannot) use message security. When streaming with the TCP binding, you also cannot enable reliable messaging.

You'll see more on security in Chapter 10.

Using streamed messages has a few additional implications. First, you need to synchronize access to the streamed content; for example, by opening the file stream in a read-only mode to allow other parties to access the file, or opening the stream in an exclusive mode to prevent others from accessing it if so required. In addition, you cannot use streaming when the contract is configured with SessionMode.Required.

..................Content has been hidden....................

You can't read the all page of ebook, please click here login for view all page.
Reset
3.146.221.144