溪流

流示例演示了流传输模式通信的使用。 该服务公开了多个用于发送和接收流的操作。 此示例是自承载的。 客户端和服务都是控制台程序。

注释

本示例的设置过程和生成说明位于本主题末尾。

Windows Communication Foundation(WCF)可以在两种传输模式(缓冲模式或流式传输模式)中进行通信。 在默认缓冲传输模式下,必须先完全传递消息,然后接收方才能读取消息。 在流传输模式下,接收方可以在消息完全传递之前开始处理消息。 当传递的信息较长且可串行处理时,流式处理模式非常有用。 当消息太大而无法完全缓冲时,流式处理模式也很有用。

流媒体和服务合同

在设计服务合同时,需要考虑流媒体技术。 如果作接收或返回大量数据,则应考虑流式传输此数据,以避免由于缓冲输入或输出消息而导致内存使用率高。 若要流式传输数据,保存该数据的参数必须是消息中唯一的参数。 例如,如果要对输入消息进行流处理,则该操作必须正好具有一个输入参数。 同样,如果要流式传输输出消息,操作必须正好具有一个输出参数或返回值。 在任一情况下,参数或返回值类型都必须为StreamMessageIXmlSerializable。 下面是该流处理示例中使用的服务协定。

[ServiceContract(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();

}

GetStream 操作接收一些输入数据作为经过缓冲的字符串,并返回经过流处理的 Stream。 相反,UploadStream 接收 Stream(流式处理),并返回 bool(缓冲)。 EchoStream 接收并返回 Stream,是一个输入和输出消息都通过流式传输的操作示例。 最后,GetReversedStream 不接受任何输入并返回一个 Stream(流式)。

启用流传输

按照上面的说明定义操作协定将在编程模型级别提供流处理。 如果停止该位置,传输仍会缓冲整个消息内容。 若要启用传输流式传输,请在传输的绑定元素上选择传输模式。 该绑定元素具有一个 TransferMode 属性,该属性可以设置为 BufferedStreamedStreamedRequestStreamedResponse。 将传输模式设置为 Streamed 将在两个方向上启用流通信。 将传输模式设置为 StreamedRequestStreamedResponse 可分别仅在请求或响应中启用流式传输通信。

basicHttpBindingTransferMode以及NetTcpBinding一样,公开了绑定上的NetNamedPipeBinding属性。 对于其他传输,必须创建一个自定义绑定以设置传输模式。

示例中的以下配置代码展示了如何将TransferMode属性设置为basicHttpBinding上的流式传输和自定义 HTTP 绑定。

<!-- An example basicHttpBinding using streaming. -->
<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>

除了将 transferMode 设置为 Streamed 之外,以前的配置代码将 maxReceivedMessageSize 设置为 64MB。 作为防御机制, maxReceivedMessageSize 将上限置于接收时允许的最大消息大小。 默认值 maxReceivedMessageSize 为 64 KB,这通常对于流式处理方案来说太低。

处理经过流处理的数据

各个操作GetStreamUploadStreamEchoStream都涉及将数据直接从文件发送或将接收到的数据直接保存到文件中。 但在某些情况下,需要发送或接收大量数据,并在发送或接收数据区块时对数据块执行一些处理。 解决此类方案的一种方法是编写一个自定义流(派生自 Stream的类),该流在读取或写入时处理数据。 GetReversedStream 操作和 ReverseStream 类是一个例子。

GetReversedStream 创建并且返回 ReverseStream 的新实例。 当系统从该 ReverseStream 对象读取时,会发生实际处理。 该 ReverseStream.Read 实现从基础文件读取字节块,反转这些字节,然后返回反向字节。 这不会扭转整个文件内容;它一次反转一个字节块。 这是一个示例,演示如何在从流读取或写入内容时执行流处理。

class ReverseStream : Stream
{

    FileStream inStream;
    internal ReverseStream(string filePath)
    {
        //Opens the file and places a StreamReader around it.
        inStream = File.OpenRead(filePath);
    }

    // Other methods removed for brevity.

    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 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;
        }

    }
}

运行示例

若要运行示例,请先按照本文档末尾的说明生成服务和客户端。 然后,在两个不同的控制台窗口中启动服务和客户端。 客户端启动时,它会等待你在服务准备就绪时按 Enter。 然后,客户端会调用这些方法 GetStream()UploadStream()GetReversedStream() 然后首先通过 HTTP,然后通过 TCP。 下面是服务的示例输出,后跟来自客户端的示例输出:

服务输出:

The streaming service is ready.
Press <ENTER> to terminate service.

Saving to file D:\...\uploadedfile
......................
File D:\...\uploadedfile saved
Saving to file D:\...\uploadedfile
...............
File D:\...\uploadedfile saved

客户端输出:

Press <ENTER> when service is ready
------ Using HTTP ------
Calling GetStream()
Saving to file D:\...\clientfile
......................
Wrote 33405 bytes to stream

File D:\...\clientfile saved
Calling UploadStream()
Calling GetReversedStream()
Saving to file D:\...\clientfile
......................
Wrote 33405 bytes to stream

File D:\...\clientfile saved
------ Using Custom HTTP ------
Calling GetStream()
Saving to file D:\...\clientfile
...............
Wrote 33405 bytes to stream

File D:\...\clientfile saved
Calling UploadStream()
Calling GetReversedStream()
Saving to file D:\...\clientfile
...............
Wrote 33405 bytes to stream

File D:\...\clientfile saved

Press <ENTER> to terminate client.

设置、生成和运行示例

  1. 确保已为 Windows Communication Foundation 示例 执行One-Time 安装过程。

  2. 若要生成解决方案的 C# 或 Visual Basic .NET 版本,请按照 生成 Windows Communication Foundation 示例中的说明进行操作。

  3. 若要在单台计算机或跨计算机配置中运行示例,请按照 运行 Windows Communication Foundation 示例中的说明进行操作。

注释

如果使用 Svcutil.exe 重新生成此示例的配置,请确保修改客户端配置中的终结点名称以匹配客户端代码。