Nasıl yapılır: Akışı Etkinleştirme

Windows Communication Foundation (WCF), arabelleğe alınan veya akışla aktarılan aktarımları kullanarak ileti gönderebilir. Varsayılan arabelleğe alınan aktarım modunda, alıcının okuyabilmesi için bir iletinin tamamen teslim edilmesi gerekir. Akış aktarım modunda, alıcı iletiyi tamamen teslim edilmeden önce işlemeye başlayabilir. Geçirilen bilgiler uzun olduğunda ve seri olarak işlenebildiğinde akış modu kullanışlıdır. Akış modu, ileti tamamen arabelleğe alınamayacak kadar büyük olduğunda da yararlıdır.

Akışı etkinleştirmek için uygun şekilde tanımlayın OperationContract ve aktarım düzeyinde akışı etkinleştirin.

Veri akışı yapmak için

  1. Veri akışı yapmak için hizmetinin OperationContract iki gereksinimi karşılaması gerekir:

    1. Akışa alınacak verileri tutan parametre yöntemindeki tek parametre olmalıdır. Örneğin, akışa alınabilecek giriş iletisiyse, işlemin tam olarak bir giriş parametresi olmalıdır. Benzer şekilde, çıkış iletisi akışla aktarılacaksa, işlemin tam olarak bir çıkış parametresi veya dönüş değeri olmalıdır.

    2. Parametre ve dönüş değeri türlerinden en az biri , Messageveya IXmlSerializableolmalıdırStream.

    Aşağıda akış verileri için bir sözleşme örneği verilmiştir.

    [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
    

    İşlem GetStream arabelleğe alınan bazı giriş verilerini arabelleğe alınan ve stringakışı yapılan bir Streamdöndürür. Buna karşılık UploadStream bir Stream (akışlı) alır ve bir bool (arabelleğe alınır) döndürür. EchoStream alır ve döndürür Stream ve giriş ve çıkış iletilerinin her ikisi de akışa alınan bir işlem örneğidir. Son olarak, GetReversedStream hiçbir giriş almaz ve bir Stream döndürür (akışlı).

  2. Akış bağlamada etkinleştirilmelidir. Aşağıdaki değerlerden birini alabilen bir TransferMode özellik ayarlarsınız:

    1. Buffered,

    2. Streamed, akış iletişimini her iki yönde de etkinleştirir.

    3. StreamedRequest, yalnızca isteğin akışını sağlar.

    4. StreamedResponse, yalnızca yanıtın akışını sağlar.

    , BasicHttpBinding ve NetNamedPipeBindinggibi NetTcpBinding bağlamada özelliğini kullanıma sunarTransferMode. Özelliği aktarım TransferMode bağlama öğesinde de ayarlanabilir ve özel bağlamada kullanılabilir.

    Aşağıdaki örneklerde koda göre ve yapılandırma dosyasını değiştirerek nasıl ayarlanacağı TransferMode gösterilmektedir. Örneklerin her ikisi de özelliğini 64 MB olarak ayarlar maxReceivedMessageSize ve bu da almada izin verilen en büyük ileti boyutuna bir üst sınır yerleştirir. Varsayılan değer maxReceivedMessageSize 64 KB'tır ve genellikle akış senaryoları için çok düşüktür. Uygulamanızın almayı beklediği ileti boyutu üst sınırına bağlı olarak bu kota ayarını uygun olarak ayarlayın. Ayrıca arabelleğe alınan en büyük boyutu denetlediğini maxBufferSize ve uygun şekilde ayarlandığını unutmayın.

    1. Örnekteki aşağıdaki yapılandırma parçacığı, ve özel bir HTTP bağlaması TransferMode üzerinde özelliğini akışa ayarlamayı basicHttpBinding gösterir.

      <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. Aşağıdaki kod parçacığı, özelliğini ve özel bir HTTP bağlaması üzerinde akışa ayarlamayı TransferModebasicHttpBinding gösterir.

      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. Aşağıdaki kod parçacığı, özelliğin özel bir TCP bağlaması üzerinde akışa ayarlanmasını TransferMode gösterir.

      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. , UploadStreamve EchoStream işlemleriGetStream, verileri doğrudan bir dosyadan gönderme veya alınan verileri doğrudan bir dosyaya kaydetme ile ilgilenir. Aşağıdaki kod içindir 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
    

Özel akış yazma

  1. Veri akışının gönderilirken veya alınırken her bir öbek üzerinde özel işlem yapmak için, öğesinden Streamözel bir akış sınıfı türetin. Özel bir akış örneği olarak, aşağıdaki kod bir GetReversedStream yöntem ve bir ReverseStream sınıf içerir.

    GetReversedStream yeni bir örneğini ReverseStreamoluşturur ve döndürür. Gerçek işleme, sistem nesneden ReverseStream okurken gerçekleşir. ReverseStream.Read yöntemi, temel alınan dosyadan bir bayt öbeği okur, bunları tersine çevirir ve ardından ters çevrilmiş baytları döndürür. Bu yöntem tüm dosya içeriğini tersine çevirmez; bir kerede bir bayt öbeklerini tersine çevirir. Bu örnek, içerik akışa okunurken veya akıştan yazılırken akış işlemeyi nasıl gerçekleştirebileceğinizi gösterir.

    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
    

Ayrıca bkz.