Compartilhar via


Fluxo

O exemplo de Streaming Demonstra o uso da comunicação no modo de transferência por streaming. O serviço expõe várias operações que enviam e recebem streaming. Este exemplo é auto-hospedado. O cliente e o serviço são programas de console.

Observação

O procedimento de instalação e as instruções de build 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 receptor possa lê-la. No modo de transferência de streaming, o receptor pode começar a processar a mensagem antes de ser completamente entregue. O modo de streaming é útil quando as informações passadas são longas e podem ser processadas serialmente. 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ê deverá considerar transmitir esses dados para evitar 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 for a que será transmitida, a operação deverá ter exatamente um parâmetro de entrada. Da mesma forma, se a mensagem de saída for transmitida, a operação deverá ter exatamente um parâmetro de saída ou um valor retornado. Em ambos os casos, o parâmetro ou tipo de valor retornado deve ser Stream, Messageou IXmlSerializable. Veja a seguir 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 (em buffer). EchoStream usa e retorna Stream e é um exemplo de uma operação cujas mensagens de entrada e saída são transmitidas. Por fim, GetReversedStream não recebe entradas e retorna um Stream (transmitido).

Habilitando transferências transmitidas

Definir 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 associação do transporte. O elemento de associação tem uma propriedade TransferMode que pode ser definida comoBuffered, Streamed, StreamedRequest ou StreamedResponse. Definir o modo de transferência para Streamed habilita a comunicação de streaming em ambas as direções. Definir o modo de transferência para StreamedRequest ou StreamedResponse habilita a comunicação de streaming apenas na solicitação ou resposta, respectivamente.

O basicHttpBinding expõe a propriedade TransferMode na associação, assim como 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 propriedade TransferMode para streaming no basicHttpBinding e em 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 64 MB. Como um 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 GetStreame UploadStreamEchoStream todas lidam com o envio de dados diretamente de um arquivo ou o salvamento de 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 conforme eles estão sendo enviados ou recebidos. Uma maneira de resolver esses cenários é gravar um fluxo personalizado (uma classe que deriva de Stream) que processa dados à medida que são lidos ou gravados. A GetReversedStream operação e ReverseStream a classe são um exemplo disso.

GetReversedStream cria e retorna uma nova instância de ReverseStream. O processamento real ocorre conforme o sistema lê desse ReverseStream objeto. A ReverseStream.Read implementação lê uma parte de bytes do arquivo subjacente, inverte-os e retorna os bytes invertidos. Isso não inverte todo o conteúdo do arquivo; inverte 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 aguarda que você pressione ENTER quando o serviço estiver pronto. Em seguida, o cliente chama os métodos GetStream()e UploadStream()GetReversedStream() , primeiro, via HTTP e, em seguida, por TCP. Aqui está um exemplo de saída do serviço seguido pela saída de exemplo 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. Verifique se você executou o Procedimento de instalação avulsa dos exemplos do Windows Communication Foundation.

  2. Para compilar a edição .NET do C# ou do Visual Basic da solução, siga as instruções contidas em Como Compilar as Amostras do Windows Communication Foundation.

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

Observação

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