Fluxo

O exemplo Stream demonstra o uso da comunicação do modo de transferência de streaming. O serviço expõe várias operações que enviam e recebem fluxos. Este exemplo é auto-hospedado. Tanto o cliente quanto o serviço são programas de console.

Nota

O procedimento de configuração e as instruções de compilação para este exemplo estão localizados no final deste tópico.

O Windows Communication Foundation (WCF) pode se comunicar em dois modos de transferência: buffer ou streaming. No modo de transferência em buffer padrão, uma mensagem deve ser completamente entregue antes que um recetor possa lê-la. No modo de transferência de streaming, o recetor pode começar a processar a mensagem antes que ela seja completamente entregue. O modo de streaming é útil quando a informação que é passada é longa e pode ser processada em série. O modo de streaming também é útil quando a mensagem é muito grande para ser totalmente armazenada em buffer.

Contratos de Streaming e Serviços

O streaming é algo a ser considerado ao projetar um contrato de serviço. Se uma operação receber ou retornar grandes quantidades de dados, você deve considerar o streaming desses dados para evitar a alta utilização de memória devido ao buffer de mensagens de entrada ou saída. Para transmitir dados, o parâmetro que contém esses dados deve ser o único parâmetro na mensagem. Por exemplo, se a mensagem de entrada é a que será transmitida, a operação deve ter exatamente um parâmetro de entrada. Da mesma forma, se a mensagem de saída deve ser transmitida, a operação deve ter exatamente um parâmetro de saída ou um valor de retorno. Em ambos os casos, o parâmetro ou o tipo de valor de retorno deve ser Stream, Messageou IXmlSerializable. A seguir está o contrato de serviço usado neste exemplo de streaming.

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

}

A GetStream operação recebe alguns dados de entrada como uma cadeia de caracteres, que é armazenada em buffer, e retorna um Stream, que é transmitido. Por outro lado, UploadStream recebe um Stream (transmitido) e retorna um bool (armazenado em buffer). EchoStream toma e retorna Stream e é um exemplo de uma operação cujas mensagens de entrada e saída são transmitidas. Finalmente, GetReversedStream não recebe entradas e retorna um Stream (transmitido).

Habilitando transferências transmitidas em fluxo

A definição de contratos de operação conforme descrito anteriormente fornece streaming no nível do modelo de programação. Se você parar por aí, o transporte ainda armazenará em buffer todo o conteúdo da mensagem. Para habilitar o streaming de transporte, selecione um modo de transferência no elemento de ligação do transporte. O elemento binding tem uma TransferMode propriedade que pode ser definida como Buffered, Streamed, StreamedRequest, ou StreamedResponse. Definir o modo de transferência para Streamed permitir a comunicação de streaming em ambas as direções. Definir o modo de transferência para StreamedRequest ou StreamedResponse permitir a comunicação de streaming apenas na solicitação ou resposta, respectivamente.

O basicHttpBinding expõe a TransferMode propriedade na vinculação como faz NetTcpBinding e NetNamedPipeBinding. Para outros transportes, você deve criar uma associação personalizada para definir o modo de transferência.

O código de configuração a seguir do exemplo mostra a configuração da TransferMode propriedade para streaming na basicHttpBinding e uma associação HTTP personalizada:

<!-- 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>

Além de definir o transferMode para Streamed, o código de configuração anterior define o maxReceivedMessageSize para 64MB. Como mecanismo de defesa, maxReceivedMessageSize coloca um limite no tamanho máximo permitido de mensagens recebidas. O padrão maxReceivedMessageSize é 64 KB, que geralmente é muito baixo para cenários de streaming.

Processando dados à medida que são transmitidos

As operações GetStream, UploadStream e EchoStream todas lidam com o envio de dados diretamente de um arquivo ou salvar os dados recebidos diretamente em um arquivo. No entanto, em alguns casos, há um requisito para enviar ou receber grandes quantidades de dados e executar algum processamento em partes dos dados à medida que são enviados ou recebidos. Uma maneira de abordar esses cenários é escrever um fluxo personalizado (uma classe que deriva de ) que processa dados à medida que são lidos Streamou gravados. A operação e ReverseStream a GetReversedStream classe são um exemplo disso.

GetReversedStream cria e retorna uma nova instância do ReverseStream. O processamento real acontece quando o sistema lê a partir desse ReverseStream objeto. A ReverseStream.Read implementação lê um pedaço de bytes do arquivo subjacente, reverte-os e, em seguida, retorna os bytes invertidos. Isso não reverte todo o conteúdo do arquivo; ele reverte um pedaço de bytes de cada vez. Este é um exemplo para mostrar como você pode executar o processamento de fluxo à medida que o conteúdo está sendo lido ou gravado de e para o fluxo.

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

    }
}

Executando o exemplo

Para executar o exemplo, primeiro crie o serviço e o cliente seguindo as instruções no final deste documento. Em seguida, inicie o serviço e o cliente em duas janelas de console diferentes. Quando o cliente é iniciado, ele espera que você pressione ENTER quando o serviço estiver pronto. Em seguida, o cliente chama os métodos GetStream()eGetReversedStream(), primeiro, UploadStream() por HTTP e depois por TCP. Aqui está um exemplo de saída do serviço seguido por exemplo de saída do cliente:

Saída do serviço:

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

Saída do cliente:

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.

Para configurar, compilar e executar o exemplo

  1. Certifique-se de ter executado o procedimento de instalação única para os exemplos do Windows Communication Foundation.

  2. Para criar a edição C# ou Visual Basic .NET da solução, siga as instruções em Criando os exemplos do Windows Communication Foundation.

  3. Para executar o exemplo em uma configuração de máquina única ou cruzada, siga as instruções em Executando os exemplos do Windows Communication Foundation.

Nota

Se você usar Svcutil.exe para regenerar a configuração para este exemplo, certifique-se de modificar o nome do ponto de extremidade na configuração do cliente para corresponder ao código do cliente.