Condividi tramite


Flusso

L'esempio stream illustra l'uso della comunicazione in modalità di trasferimento in streaming. Il servizio espone diverse operazioni che inviano e ricevono flussi di dati. Questo esempio è ospitato internamente. Sia il client che il servizio sono programmi console.

Annotazioni

La procedura di installazione e le istruzioni di compilazione per questo esempio si trovano alla fine di questo argomento.

Windows Communication Foundation (WCF) può comunicare in due modalità di trasferimento, memorizzate nel buffer o in streaming. Nella modalità di trasferimento memorizzato nel buffer predefinita, è necessario recapitare completamente un messaggio prima che un ricevitore possa leggerlo. Nella modalità di trasferimento in streaming, il ricevitore può iniziare a elaborare il messaggio prima che venga recapitato completamente. La modalità di streaming è utile quando le informazioni passate sono lunghe e possono essere elaborate in modo seriale. La modalità di streaming è utile anche quando il messaggio è troppo grande per essere interamente memorizzato nel buffer.

Streaming e contratti di servizio

Lo streaming è un elemento da considerare durante la progettazione di un contratto di servizio. Se un'operazione riceve o restituisce grandi quantità di dati, è consigliabile eseguire lo streaming di questi dati per evitare un utilizzo elevato della memoria a causa del buffer dei messaggi di input o di output. Per trasmettere i dati, il parametro che contiene tali dati deve essere l'unico parametro nel messaggio. Ad esempio, se il messaggio di input è quello da trasmettere, l'operazione deve avere esattamente un parametro di input. Analogamente, se il messaggio di output deve essere trasmesso, l'operazione deve avere esattamente un parametro di output o un valore restituito. In entrambi i casi, il tipo di parametro o valore restituito deve essere Stream, Messageo IXmlSerializable. Di seguito è riportato il contratto di servizio usato in questo esempio di 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();

}

L'operazione GetStream riceve dei dati di input come stringa, li memorizza nel buffer e restituisce un Stream, che viene trasmesso in streaming. Viceversa, UploadStream accetta un oggetto Stream (trasmesso) e restituisce un bool oggetto (memorizzato nel buffer). EchoStream accetta e restituisce Stream ed è un esempio di un'operazione i cui messaggi di input e output sono entrambi trasmessi. Infine, GetReversedStream non accetta input e restituisce un oggetto Stream (trasmesso).

Attivazione dei trasferimenti con flusso

La definizione dei contratti di operazione come descritto in precedenza fornisce lo streaming a livello di modello di programmazione. Se ti fermi, il trasporto memorizza comunque nel buffer l'intero contenuto del messaggio. Per abilitare lo streaming del trasporto, selezionare una modalità di trasferimento nell'elemento di associazione del trasporto. L'elemento di associazione presenta una proprietà TransferMode che può essere impostata su Buffered, Streamed, StreamedRequest o StreamedResponse. L'impostazione della modalità di trasferimento su Streamed consente di attivare la comunicazione con flusso bidirezionale. Impostando la modalità di trasferimento su StreamedRequest o su StreamedResponse, si abilita la comunicazione di streaming solo nella richiesta o nella risposta, rispettivamente.

basicHttpBinding espone la proprietà sull'associazione TransferMode così come NetTcpBinding e NetNamedPipeBinding. Per impostare la modalità di trasferimento degli altri trasporti è necessario creare un'associazione personalizzata.

Il seguente codice di configurazione dell'esempio mostra come impostare la proprietà TransferMode su streaming su basicHttpBinding e un binding HTTP personalizzato.

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

Oltre a impostare il transferMode su Streamed, il codice di configurazione precedente imposta il maxReceivedMessageSize su 64 MB. Come meccanismo di difesa, maxReceivedMessageSize posiziona un limite sulle dimensioni massime consentite dei messaggi alla ricezione. Il valore predefinito maxReceivedMessageSize è 64 KB, che in genere è troppo basso per gli scenari di streaming.

Elaborazione dei dati durante lo streaming

Le operazioni GetStreamUploadStream e EchoStream tutte gestiscono l'invio di dati direttamente da un file o il salvataggio dei dati ricevuti direttamente in un file. In alcuni casi, tuttavia, è necessario inviare o ricevere grandi quantità di dati ed eseguire un'elaborazione in blocchi dei dati man mano che vengono inviati o ricevuti. Un modo per affrontare questi scenari consiste nel scrivere un flusso personalizzato (una classe che deriva da Stream) che elabora i dati durante la lettura o la scrittura. L'operazione GetReversedStream e ReverseStream la classe sono un esempio di questo.

GetReversedStream crea e restituisce una nuova istanza di ReverseStream. L'elaborazione effettiva avviene quando il sistema legge da tale ReverseStream oggetto. L'implementazione ReverseStream.Read legge un blocco di byte dal file sottostante, li inverte, quindi restituisce i byte invertiti. Questo non inverte l'intero contenuto del file; inverte un blocco di byte alla volta. Questo è un esempio per mostrare come è possibile eseguire l'elaborazione del flusso quando il contenuto viene letto o scritto da e nel flusso.

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

    }
}

Esecuzione dell'esempio

Per eseguire l'esempio, compilare prima sia il servizio che il client seguendo le istruzioni alla fine di questo documento. Avviare quindi il servizio e il client in due diverse finestre della console. All'avvio del client, attende di premere INVIO quando il servizio è pronto. Il client chiama quindi i metodi GetStream()UploadStream() e GetReversedStream() prima su HTTP e quindi su TCP. Di seguito è riportato un esempio di output del servizio seguito dall'output di esempio del client:

Output del servizio:

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

Output del client:

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.

Per configurare, compilare ed eseguire l'esempio

  1. Assicurati di aver eseguito la procedura di installazione di One-Time per gli esempi di Windows Communication Foundation.

  2. Per compilare l'edizione C# o Visual Basic .NET della soluzione, seguire le istruzioni in Compilazione degli esempi di Windows Communication Foundation.

  3. Per eseguire l'esempio in una configurazione con computer singolo o incrociato, seguire le istruzioni riportate in Esecuzione degli esempi di Windows Communication Foundation.

Annotazioni

Se si usa Svcutil.exe per rigenerare la configurazione per questo esempio, assicurarsi di modificare il nome dell'endpoint nella configurazione client in modo che corrisponda al codice client.