方法: ストリーミングを有効にするHow to: Enable Streaming

Windows Communication Foundation (WCF) では、ストリームまたはバッファー内のいずれかの転送を使用してメッセージを送信できます。Windows Communication Foundation (WCF) can send messages using either buffered or streamed transfers. 既定のバッファー転送モードでは、受信側がメッセージを読み取る前に、メッセージの送信が完了している必要があります。In the default buffered-transfer mode, a message must be completely delivered before a receiver can read it. ストリーミング転送モードでは、送信が完了していなくても、受信側でメッセージの処理を開始できます。In streaming transfer mode, the receiver can begin to process the message before it is completely delivered. ストリーミング モードは、渡される情報が長い場合、または連続的に処理する場合に役立ちます。The streaming mode is useful when the information that is passed is lengthy and can be processed serially. ストリーミング モードは、メッセージが大きすぎてすべてをバッファーできない場合にも役立ちます。Streaming mode is also useful when the message is too large to be entirely buffered.

ストリーミングを有効にするには、OperationContract を適切に定義し、トランスポート レベルでストリーミングを有効にします。To enable streaming, define the OperationContract appropriately and enable streaming at the transport level.

データをストリーミングするにはTo stream data

  1. データをストリーミングするには、サービスの OperationContract が次の 2 つの要件を満たしている必要があります。To stream data, the OperationContract for the service must satisfy two requirements:

    1. ストリーミングするデータを保持するパラメーターが、メソッド内の唯一のパラメーターになるようにします。The parameter that holds the data to be streamed must be the only parameter in the method. たとえば、入力メッセージをストリーミングする場合、厳密に 1 つの入力パラメーターが操作に含まれている必要があります。For example, if the input message is the one to be streamed, the operation must have exactly one input parameter. 同様に、出力メッセージをストリーミングする場合、厳密に 1 つの出力パラメーターまたは戻り値が操作に含まれている必要があります。Similarly, if the output message is to be streamed, the operation must have either exactly one output parameter or a return value.

    2. パラメーターおよび戻り値の型の少なくとも 1 つが、StreamMessage または IXmlSerializable になる必要があります。At least one of the types of the parameter and return value must be either Stream, Message, or IXmlSerializable.

    ストリーミングされたデータのコントラクトの例を次に示します。The following is an example of a contract for streamed data.

    [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
    

    GetStream 操作は、バッファーされた入力データを string として受信し、ストリーミングされた Stream を返します。The GetStream operation receives some buffered input data as a string, which is buffered, and returns a Stream, which is streamed. 逆に言えば、UploadStreamStream (ストリーミング) を取り込んで、bool (バッファー) を返します。Conversely UploadStream takes in a Stream (streamed) and returns a bool (buffered). EchoStreamStream を出し入れします。これは、入力および出力メッセージがどちらもストリーミングされる操作の例です。EchoStream takes and returns Stream and is an example of an operation whose input and output messages are both streamed. 最後に、GetReversedStream は入力を行わずに Stream (ストリーミング) を返します。Finally, GetReversedStream takes no inputs and returns a Stream (streamed).

  2. バインディングではストリーミングを有効にする必要があります。Streaming must be enabled on the binding. TransferMode プロパティを次の値のいずれかに設定します。You set a TransferMode property, which can take one of the following values:

    1. BufferedBuffered,

    2. Streamed (両方向のストリーミング通信を有効にする)。Streamed, which enables streaming communication in both directions.

    3. StreamedRequest (要求に対してのみストリーミングを有効にする)。StreamedRequest, which enables streaming the request only.

    4. StreamedResponse (応答に対してのみストリーミングを有効にする)。StreamedResponse, which enables streaming the response only.

    BasicHttpBinding は、バインディングの TransferMode プロパティを公開し、NetTcpBindingNetNamedPipeBinding も公開します。The BasicHttpBinding exposes the TransferMode property on the binding, as does NetTcpBinding and NetNamedPipeBinding. TransferMode プロパティをトランスポート バインド要素に設定し、カスタム バインドで使用することもできます。The TransferMode property can also be set on the transport binding element and used in a custom binding.

    次のサンプルは、コードで TransferMode を設定する方法と、構成ファイルを変更して設定する方法を示しています。The following samples show how to set TransferMode by code and by changing the configuration file. どちらのサンプルも、受信可能なメッセージの最大サイズを決定する maxReceivedMessageSize プロパティを 64 MB に設定します。The samples also both set the maxReceivedMessageSize property to 64 MB, which places a cap on the maximum allowable size of messages on receive. 既定の maxReceivedMessageSize は 64 KB です。これは、多くの場合ストリーミングを行うには小さすぎます。The default maxReceivedMessageSize is 64 KB, which is usually too low for streaming scenarios. アプリケーションでの受信が予想されるメッセージ最大サイズに応じて、このクォータ設定を適切に変更してください。Set this quota setting as appropriate depending on the maximum size of messages your application expects to receive. また、maxBufferSize によりバッファーの最大サイズが決定されるので、適切に設定してください。Also note that maxBufferSize controls the maximum size that is buffered, and set it appropriately.

    1. 次のサンプルの構成スニペットでは、TransferMode とカスタム HTTP バインディングで、basicHttpBinding プロパティをストリーミングに設定しています。The following configuration snippet from the sample shows setting the TransferMode property to streaming on the basicHttpBinding and a custom HTTP binding.

      <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. 次のコード スニペットでは、TransferMode とカスタム HTTP バインディングで、basicHttpBinding プロパティをストリーミングに設定しています。The following code snippet shows setting the TransferMode property to streaming on the basicHttpBinding and a custom HTTP binding.

      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. 次のコード スニペットでは、カスタム TCP バインディングで、TransferMode プロパティをストリーミングに設定しています。The following code snippet shows setting the TransferMode property to streaming on a custom TCP binding.

      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. GetStreamUploadStream、および EchoStream の各操作では、ファイルからデータを直接送信したり、受信したデータを直接ファイルに保存します。The operations GetStream, UploadStream, and EchoStream all deal with sending data directly from a file or saving received data directly to a file. 次のコードは、GetStream の例です。The following code is for 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
    

カスタム ストリームの書き込みWriting a custom stream

  1. 送受信中のデータ ストリームの各チャンクに対して特殊な処理を行うには、Stream からカスタム ストリーム クラスを派生します。To do special processing on each chunk of a data stream as it is being sent or received, derive a custom stream class from Stream. カスタム ストリームの例として、GetReversedStream メソッドと ReverseStream クラスのコードを次に示します。As an example of a custom stream, the following code contains a GetReversedStream method and a ReverseStream class-.

    GetReversedStream では、ReverseStream の新しいインスタンスを作成して返します。GetReversedStream creates and returns a new instance of ReverseStream. 実際の処理は、システムが ReverseStream オブジェクトの読み取りを行うときに発生します。The actual processing happens as the system reads from the ReverseStream object. ReverseStream.Read メソッドは、基になるファイルからバイトのチャンクを読み取り、バイトを反転し、その反転したバイトを返します。The ReverseStream.Read method reads a chunk of bytes from the underlying file, reverses them, then returns the reversed bytes. このメソッドは、ファイル全体の内容を反転しません。一度に 1 つのバイト チャンクを反転します。This method does not reverse the entire file content; it reverses one chunk of bytes at a time. この例では、ストリームの内容の読み取りやストリームへの書き込み時に、ストリーミング処理を実行する方法を示します。This example shows how you can perform stream processing as the content is being read to or written from the 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
    

関連項目See also