Share via


Cara: Mengaktifkan Streaming

Windows Communication Foundation (WCF) dapat mengirim pesan menggunakan transfer aliran atau buffer. Dalam mode transfer buffer default, pesan harus sepenuhnya dikirim sebelum penerima bisa membacanya. Dalam mode transfer streaming, penerima dapat mulai memproses pesan sebelum dikirim sepenuhnya. Mode streaming berguna saat informasi yang diteruskan isinya panjang dan dapat diproses secara serial. Mode streaming juga berguna saat pesan terlalu besar untuk sepenuhnya di-buffer.

Untuk mengaktifkan streaming, tentukan OperationContract dengan tepat dan aktifkan streaming di tingkat transportasi.

Untuk streaming data

  1. Untuk streaming data, OperationContract untuk layanan harus memenuhi dua persyaratan:

    1. Parameter berisi data yang akan di-streaming harus menjadi satu-satunya parameter dalam metode ini. Misalnya, jika pesan input adalah yang akan di-streaming, operasi harus memiliki satu parameter input. Demikian pula, jika pesan output akan dialirkan, operasi harus memiliki tepat satu parameter output atau nilai yang dikembalikan.

    2. Setidaknya salah satu jenis parameter dan nilai yang ditampilkan harus, Stream, Message atau IXmlSerializable.

    Berikut ini adalah contoh kontrak untuk data yang 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();
    }
    
    <ServiceContract(Namespace:="http://Microsoft.ServiceModel.Samples")> _
    Public Interface IStreamingSample
        <OperationContract()> _
        Function GetStream(ByVal data As String) As Stream
        <OperationContract()> _
        Function UploadStream(ByVal stream As Stream) As Boolean
        <OperationContract()> _
        Function EchoStream(ByVal stream As Stream) As Stream
        <OperationContract()> _
        Function GetReversedStream() As Stream
    
    End Interface
    

    Operasi GetStream menerima beberapa data input buffer sebagai string, yang di-buffer, dan menampilkan Stream, yang di-streaming. Sebaliknya UploadStream menggunakan Stream (di-streaming) dan menampilkan bool (di-buffer). EchoStream menggunakan dan menampilkan Stream dan merupakan contoh operasi yang pesan input dan output-nya di-streaming. Di akhir, GetReversedStream tidak menggunakan input dan menampilkan Stream (di-streaming).

  2. Streaming harus diaktifkan pada pengikatan. Anda menetapkan properti TransferMode, yang dapat menggunakan salah satu nilai berikut:

    1. Buffered,

    2. Streamed, yang memungkinkan komunikasi streaming secara dua arah.

    3. StreamedRequest, yang memungkinkan streaming permintaan saja.

    4. StreamedResponse, yang memungkinkan streaming respons saja.

    BasicHttpBinding mengekspos properti TransferMode pada pengikatan, seperti halnya NetTcpBinding dan NetNamedPipeBinding. Properti TransferMode juga bisa diatur pada elemen pengikatan transportasi dan digunakan dalam pengikatan kustom.

    Sampel berikut menunjukkan cara mengatur TransferMode menurut kode dan dengan mengubah file konfigurasi. Sampel juga keduanya mengatur properti maxReceivedMessageSize ke 64 MB, yang menempatkan batas pada ukuran maksimum pesan yang diizinkan saat menerima. Defaultnya maxReceivedMessageSize adalah 64 KB, yang biasanya terlalu rendah untuk skenario streaming. Atur pengaturan kuota ini sesuai ukuran maksimum pesan yang diharapkan diterima aplikasi Anda. Perhatikan juga bahwa maxBufferSize mengontrol ukuran maksimum yang di-buffer, dan atur dengan tepat.

    1. Cuplikan konfigurasi berikut dari sampel menunjukkan pengaturan properti TransferMode ke streaming pada basicHttpBinding dan pengikatan HTTP kustom.

      <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>
      
    2. Cuplikan kode berikut menunjukkan pengaturan properti TransferMode ke streaming pada basicHttpBinding dan pengikatan HTTP kustom.

      public static Binding CreateStreamingBinding()
      {
          BasicHttpBinding b = new BasicHttpBinding();
          b.TransferMode = TransferMode.Streamed;
          return b;
      }
      
      Public Shared Function CreateStreamingBinding() As Binding
          Dim b As New BasicHttpBinding()
          b.TransferMode = TransferMode.Streamed
          Return b
      End Function
      
    3. Cuplikan kode berikut menunjukkan pengaturan properti TransferMode ke streaming pada pengikatan TCP kustom.

      public static Binding CreateStreamingBinding()
      {
          TcpTransportBindingElement transport = new TcpTransportBindingElement();
          transport.TransferMode = TransferMode.Streamed;
          BinaryMessageEncodingBindingElement encoder = new BinaryMessageEncodingBindingElement();
          CustomBinding binding = new CustomBinding(encoder, transport);
          return binding;
      }
      
      Public Shared Function CreateStreamingBinding() As Binding
          Dim transport As New TcpTransportBindingElement()
          transport.TransferMode = TransferMode.Streamed
          Dim binding As New CustomBinding(New BinaryMessageEncodingBindingElement(), _
                                           transport)
          Return binding
      End Function
      
  3. Operasi GetStream, UploadStream, dan EchoStream semua berurusan dengan pengiriman data langsung dari file atau menyimpan data yang diterima langsung ke file. Kode berikut adalah untuk GetStream.

    public Stream GetStream(string data)
    {
        //this file path assumes the image is in
        // the Service folder and the service is executing
        // in service/bin
        string filePath = Path.Combine(
            System.Environment.CurrentDirectory,
            ".\\..\\image.jpg");
        //open the file, this could throw an exception
        //(e.g. if the file is not found)
        //having includeExceptionDetailInFaults="True" in config
        // would cause this exception to be returned to the client
        try
        {
            FileStream imageFile = File.OpenRead(filePath);
            return imageFile;
        }
        catch (IOException ex)
        {
            Console.WriteLine(
                String.Format("An exception was thrown while trying to open file {0}", filePath));
            Console.WriteLine("Exception is: ");
            Console.WriteLine(ex.ToString());
            throw ex;
        }
    }
    
    Public Function GetStream(ByVal data As String) As Stream Implements IStreamingSample.GetStream
        'this file path assumes the image is in
        ' the Service folder and the service is executing
        ' in service/bin 
        Dim filePath = Path.Combine(System.Environment.CurrentDirectory, ".\..\image.jpg")
        'open the file, this could throw an exception 
        '(e.g. if the file is not found)
        'having includeExceptionDetailInFaults="True" in config 
        ' would cause this exception to be returned to the client
        Try
            Return File.OpenRead(filePath)
        Catch ex As IOException
            Console.WriteLine(String.Format("An exception was thrown while trying to open file {0}", filePath))
            Console.WriteLine("Exception is: ")
            Console.WriteLine(ex.ToString())
            Throw ex
        End Try
    End Function
    

Menulis stream kustom

  1. Untuk melakukan pemrosesan khusus pada setiap potongan aliran data saat dikirim atau diterima, dapatkan kelas stream kustom dari Stream. Sebagai contoh stream kustom, kode berikut berisi metode GetReversedStream dan kelas ReverseStream.

    GetReversedStream membuat dan menampilkan instans baru ReverseStream. Pemrosesan aktual terjadi saat sistem membaca dari objek ReverseStream. Metode ReverseStream.Read ini membaca potongan byte dari file yang mendasarinya, membaliknya, lalu menampilkan byte terbalik. Metode ini tidak membalikkan seluruh konten file; hanya membalikkan satu potongan byte pada satu waktu. Contoh ini menunjukkan cara melakukan pemrosesan streaming saat konten sedang dibaca atau ditulis dari stream.

    class ReverseStream : Stream
    {
    
        FileStream inStream;
        internal ReverseStream(string filePath)
        {
            //opens the file and places a StreamReader around it
            inStream = File.OpenRead(filePath);
        }
        public override bool CanRead
        {
            get { return inStream.CanRead; }
        }
    
        public override bool CanSeek
        {
            get { return false; }
        }
    
        public override bool CanWrite
        {
            get { return false; }
        }
    
        public override void Flush()
        {
            throw new Exception("This stream does not support writing.");
        }
    
        public override long Length
        {
            get { throw new Exception("This stream does not support the Length property."); }
        }
    
        public override long Position
        {
            get
            {
                return inStream.Position;
            }
            set
            {
                throw new Exception("This stream does not support setting the Position property.");
            }
        }
    
        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 long Seek(long offset, SeekOrigin origin)
        {
            throw new Exception("This stream does not support seeking.");
        }
    
        public override void SetLength(long value)
        {
            throw new Exception("This stream does not support setting the Length.");
        }
    
        public override void Write(byte[] buffer, int offset, int count)
        {
            throw new Exception("This stream does not support writing.");
        }
        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;
            }
        }
    }
    
    Friend Class ReverseStream
        Inherits Stream
    
        Private inStream As FileStream
    
        Friend Sub New(ByVal filePath As String)
            'opens the file and places a StreamReader around it
            inStream = File.OpenRead(filePath)
        End Sub
    
        Public Overrides ReadOnly Property CanRead() As Boolean
            Get
                Return inStream.CanRead
            End Get
        End Property
    
        Public Overrides ReadOnly Property CanSeek() As Boolean
            Get
                Return False
            End Get
        End Property
    
        Public Overrides ReadOnly Property CanWrite() As Boolean
            Get
                Return False
            End Get
        End Property
    
        Public Overrides Sub Flush()
            Throw New Exception("This stream does not support writing.")
        End Sub
    
        Public Overrides ReadOnly Property Length() As Long
            Get
                Throw New Exception("This stream does not support the Length property.")
            End Get
        End Property
    
        Public Overrides Property Position() As Long
            Get
                Return inStream.Position
            End Get
            Set(ByVal value As Long)
                Throw New Exception("This stream does not support setting the Position property.")
            End Set
        End Property
    
        Public Overrides Function Read(ByVal buffer() As Byte, _
                                       ByVal offset As Integer, _
                                       ByVal count As Integer) As Integer
    
            Dim countRead = inStream.Read(buffer, _
                                          offset, _
                                          count)
            ReverseBuffer(buffer, _
                          offset, _
                          countRead)
            Return countRead
        End Function
    
        Public Overrides Function Seek(ByVal offset As Long, _
                                       ByVal origin As SeekOrigin) As Long
            Throw New Exception("This stream does not support seeking.")
        End Function
    
        Public Overrides Sub SetLength(ByVal value As Long)
            Throw New Exception("This stream does not support setting the Length.")
        End Sub
    
        Public Overrides Sub Write(ByVal buffer() As Byte, _
                                   ByVal offset As Integer, _
                                   ByVal count As Integer)
            Throw New Exception("This stream does not support writing.")
        End Sub
    
        Public Overrides Sub Close()
            inStream.Close()
            MyBase.Close()
        End Sub
    
        Protected Overloads Overrides Sub Dispose(ByVal disposing As Boolean)
            inStream.Dispose()
            MyBase.Dispose(disposing)
        End Sub
    
        Private Sub ReverseBuffer(ByVal buffer() As Byte, _
                                  ByVal offset As Integer, _
                                  ByVal count As Integer)
    
            Dim i = offset
            Dim j = offset + count - 1
    
            Do While i < j
                Dim currenti = buffer(i)
                buffer(i) = buffer(j)
                buffer(j) = currenti
                i += 1
                j -= 1
            Loop
    
        End Sub
    End Class
    

Lihat juga