Procedure: Streaming inschakelen
Windows Communication Foundation (WCF) kan berichten verzenden met behulp van gebufferde of gestreamde overdrachten. In de standaardmodus voor gebufferde overdracht moet een bericht volledig worden bezorgd voordat een ontvanger het kan lezen. In de streamingoverdrachtmodus kan de ontvanger het bericht verwerken voordat het volledig wordt bezorgd. De streamingmodus is handig wanneer de informatie die wordt doorgegeven, lang is en serieel kan worden verwerkt. De streamingmodus is ook handig wanneer het bericht te groot is om volledig te worden gebufferd.
Als u streaming wilt inschakelen, definieert u de OperationContract
juiste en schakelt u streaming in op transportniveau.
Gegevens streamen
Als u gegevens wilt streamen, moet de
OperationContract
service aan twee vereisten voldoen:De parameter die de gegevens bevat die moeten worden gestreamd, moet de enige parameter in de methode zijn. Als het invoerbericht bijvoorbeeld het bericht is dat moet worden gestreamd, moet de bewerking precies één invoerparameter hebben. Als het uitvoerbericht moet worden gestreamd, moet de bewerking ook exact één uitvoerparameter of een retourwaarde hebben.
Ten minste één van de typen van de parameter en retourwaarde moet Streamofwel , Messageof IXmlSerializable.
Hier volgt een voorbeeld van een contract voor gestreamde gegevens.
[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
De
GetStream
bewerking ontvangt enkele gebufferde invoergegevens als eenstring
, die wordt gebufferd en retourneert eenStream
, die wordt gestreamd. Neemt daarentegenUploadStream
eenStream
(gestreamd) en retourneert eenbool
(gebufferd).EchoStream
neemt en retourneertStream
en is een voorbeeld van een bewerking waarvan de invoer- en uitvoerberichten beide worden gestreamd.GetReversedStream
Neemt ten slotte geen invoer en retourneert eenStream
(gestreamde) invoer.Streaming moet zijn ingeschakeld voor de binding. U stelt een
TransferMode
eigenschap in, die een van de volgende waarden kan aannemen:Buffered
,Streamed
, waardoor streamingcommunicatie in beide richtingen mogelijk is.StreamedRequest
, waarmee de aanvraag alleen kan worden gestreamd.StreamedResponse
, waarmee het antwoord alleen kan worden gestreamd.
De
BasicHttpBinding
eigenschap wordtTransferMode
weergegeven op de binding, zoals welNetTcpBinding
enNetNamedPipeBinding
. DeTransferMode
eigenschap kan ook worden ingesteld op het transportbindingselement en wordt gebruikt in een aangepaste binding.In de volgende voorbeelden ziet u hoe u kunt instellen
TransferMode
op code en door het configuratiebestand te wijzigen. De voorbeelden stellen de eigenschap ook in op 64 MB, waardoor een limiet wordt ingesteldmaxReceivedMessageSize
op de maximaal toegestane grootte van berichten die worden ontvangen. De standaardwaardemaxReceivedMessageSize
is 64 kB, wat meestal te laag is voor streamingscenario's. Stel deze quotuminstelling in, afhankelijk van de maximale grootte van berichten die uw toepassing verwacht te ontvangen. Houd er ook rekening mee datmaxBufferSize
u de maximale grootte bepaalt die wordt gebufferd en op de juiste manier wordt ingesteld.In het volgende configuratiefragment uit het voorbeeld ziet u hoe u de
TransferMode
eigenschap instelt op streaming op debasicHttpBinding
en een aangepaste 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>
Het volgende codefragment toont het instellen van de
TransferMode
eigenschap op streaming op debasicHttpBinding
en een aangepaste 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
Het volgende codefragment toont het instellen van de
TransferMode
eigenschap op streaming op een aangepaste 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
De bewerkingen,
UploadStream
enEchoStream
alle bewerkingenGetStream
hebben betrekking op het rechtstreeks verzenden van gegevens uit een bestand of het rechtstreeks opslaan van ontvangen gegevens naar een bestand. De volgende code is bedoeld voorGetStream
.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
Een aangepaste stream schrijven
Als u speciale verwerking wilt uitvoeren op elk segment van een gegevensstroom terwijl deze wordt verzonden of ontvangen, moet u een aangepaste stroomklasse afleiden van Stream. Als voorbeeld van een aangepaste stream bevat de volgende code een
GetReversedStream
methode en eenReverseStream
klasse.GetReversedStream
maakt en retourneert een nieuw exemplaar vanReverseStream
. De werkelijke verwerking vindt plaats wanneer het systeem uit hetReverseStream
object leest. DeReverseStream.Read
methode leest een segment van bytes uit het onderliggende bestand, keert deze om en retourneert vervolgens de omgekeerde bytes. Met deze methode wordt de volledige bestandsinhoud niet omgekeerd; hiermee wordt één segment van bytes tegelijk omgekeerd. In dit voorbeeld ziet u hoe u stroomverwerking kunt uitvoeren terwijl de inhoud wordt gelezen naar of geschreven vanuit de 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