Postupy: Povolení streamování
Windows Communication Foundation (WCF) může odesílat zprávy buď pomocí vyrovnávací paměti, nebo streamovaných přenosů. Ve výchozím režimu přenosu do vyrovnávací paměti musí být zpráva zcela doručena, aby ji příjemce mohl přečíst. V režimu přenosu streamování může příjemce začít zpracovávat zprávu před tím, než se zcela doručí. Režim streamování je užitečný, pokud jsou předané informace dlouhé a lze je zpracovat sériově. Režim streamování je také užitečný, pokud je zpráva příliš velká, aby byla zcela uložena do vyrovnávací paměti.
Pokud chcete povolit streamování, definujte OperationContract
správně a povolte streamování na úrovni přenosu.
Streamování dat
Pokud chcete streamovat data,
OperationContract
musí služba splňovat dvě požadavky:Parametr, který obsahuje data, která se mají streamovat, musí být jediným parametrem v metodě. Pokud je vstupní zpráva například ta, která se má streamovat, musí mít operace přesně jeden vstupní parametr. Podobně platí, že pokud se má streamovat výstupní zpráva, musí mít operace buď přesně jeden výstupní parametr, nebo návratovou hodnotu.
Nejméně jeden z typů parametru a návratová hodnota musí být buď Stream, Messagenebo IXmlSerializable.
Následuje příklad kontraktu pro streamovaná 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
Operace
GetStream
obdrží některá vstupní data uložená do vyrovnávací paměti jakostring
vyrovnávací paměť a vrátíStream
, která se streamuje.UploadStream
Naopak přebíráStream
(streamovaný) a vracíbool
(vyrovnávací paměť).EchoStream
přijímá a vracíStream
a je příkladem operace, jejíž vstupní a výstupní zprávy se streamují.GetReversedStream
Nakonec nepřijímá žádné vstupy a vracíStream
(streamovaný).U vazby musí být povolené streamování.
TransferMode
Nastavíte vlastnost, která může mít jednu z následujících hodnot:Buffered
,Streamed
, která umožňuje streamovat komunikaci v obou směrech.StreamedRequest
, což umožňuje pouze streamování požadavku.StreamedResponse
, což umožňuje streamování pouze odpovědi.
Zpřístupňuje
BasicHttpBinding
vlastnost vazbyTransferMode
, stejně jakoNetTcpBinding
aNetNamedPipeBinding
. VlastnostTransferMode
lze také nastavit pro element vazby přenosu a použít ve vlastní vazbě.Následující ukázky ukazují, jak nastavit
TransferMode
kód a změnit konfigurační soubor. Ukázky také nastavímaxReceivedMessageSize
vlastnost na 64 MB, což umístí limit na maximální povolenou velikost zpráv při příjmu. Výchozí hodnotamaxReceivedMessageSize
je 64 kB, což je obvykle příliš nízké pro scénáře streamování. Nastavte toto nastavení kvóty podle potřeby v závislosti na maximální velikosti zpráv, které vaše aplikace očekává. Všimněte si také, žemaxBufferSize
řídí maximální velikost uloženou do vyrovnávací paměti a odpovídajícím způsobem ji nastavte.Následující fragment kódu konfigurace z ukázky ukazuje nastavení
TransferMode
vlastnosti na streamování ubasicHttpBinding
vlastní vazby HTTP.<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>
Následující fragment kódu ukazuje nastavení
TransferMode
vlastnosti streamování nabasicHttpBinding
vlastní vazbu HTTP.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
Následující fragment kódu ukazuje nastavení
TransferMode
vlastnosti streamování na vlastní vazbu TCP.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
GetStream
Operace aUploadStream
EchoStream
všechny se zabývají odesíláním dat přímo ze souboru nebo ukládáním přijatých dat přímo do souboru. Následující kód je určen proGetStream
.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
Zápis vlastního datového proudu
Chcete-li provést speciální zpracování na každém bloku datového proudu při jejich odesílání nebo přijetí, odvodit vlastní třídu streamu z Stream. Jako příklad vlastního streamu obsahuje následující kód metodu
GetReversedStream
ReverseStream
a třídu.GetReversedStream
vytvoří a vrátí novou instanci .ReverseStream
Skutečné zpracování probíhá, když systém čte z objektuReverseStream
. MetodaReverseStream.Read
načte blok bajtů z podkladového souboru, vrátí je zpět a vrátí obrácené bajty. Tato metoda nevrátí celý obsah souboru; obrátí jeden blok bajtů najednou. Tento příklad ukazuje, jak můžete provádět zpracování datových proudů při čtení nebo zápisu obsahu ze streamu.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