Stream
W przykładzie usługi Stream pokazano użycie komunikacji w trybie transferu przesyłania strumieniowego. Usługa uwidacznia kilka operacji, które wysyłają i odbierają strumienie. Ten przykład jest hostowany samodzielnie. Zarówno klient, jak i usługa to programy konsolowe.
Uwaga
Procedura instalacji i instrukcje kompilacji dla tego przykładu znajdują się na końcu tego tematu.
Program Windows Communication Foundation (WCF) może komunikować się w dwóch trybach transferu — buforowanych lub przesyłanych strumieniowo. W domyślnym trybie buforowanego transferu komunikat musi zostać całkowicie dostarczony, zanim odbiorca będzie mógł go odczytać. W trybie transferu przesyłania strumieniowego odbiornik może rozpocząć przetwarzanie komunikatu przed jego całkowitym dostarczeniem. Tryb przesyłania strumieniowego jest przydatny, gdy przekazywane informacje są długie i mogą być przetwarzane szeregowo. Tryb przesyłania strumieniowego jest również przydatny, gdy komunikat jest zbyt duży, aby był całkowicie buforowany.
Przesyłanie strumieniowe i kontrakty usług
Przesyłanie strumieniowe to coś, co należy wziąć pod uwagę podczas projektowania kontraktu usługi. Jeśli operacja odbiera lub zwraca duże ilości danych, należy rozważyć przesyłanie strumieniowe tych danych, aby uniknąć wysokiego wykorzystania pamięci z powodu buforowania komunikatów wejściowych lub wyjściowych. Aby przesyłać strumieniowo dane, parametr, który przechowuje dane, musi być jedynym parametrem w komunikacie. Jeśli na przykład komunikat wejściowy jest przesyłany strumieniowo, operacja musi mieć dokładnie jeden parametr wejściowy. Podobnie, jeśli komunikat wyjściowy ma być przesyłany strumieniowo, operacja musi mieć dokładnie jeden parametr wyjściowy lub wartość zwracaną. W obu przypadkach parametr lub zwracany typ wartości musi mieć Stream
wartość , Message
lub IXmlSerializable
. Poniżej przedstawiono kontrakt usługi używany w tym przykładzie przesyłania strumieniowego.
[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();
}
Operacja GetStream
odbiera dane wejściowe jako ciąg, który jest buforowany i zwraca Stream
element , który jest przesyłany strumieniowo. Z drugiej strony przyjmuje UploadStream
wartość (przesyłaną strumieniowo Stream
) i zwraca bool
wartość (buforowaną). EchoStream
przyjmuje i zwraca Stream
i jest przykładem operacji, której komunikaty wejściowe i wyjściowe są przesyłane strumieniowo. Na koniec nie GetReversedStream
przyjmuje żadnych danych wejściowych i zwraca wartość Stream
(przesyłana strumieniowo).
Włączanie strumieniowych transferów
Definiowanie kontraktów operacji zgodnie z wcześniejszym opisem zapewnia przesyłanie strumieniowe na poziomie modelu programowania. Jeśli się tam zatrzymasz, transport nadal buforuje całą zawartość komunikatu. Aby włączyć przesyłanie strumieniowe transportu, wybierz tryb transferu dla elementu powiązania transportu. Element powiązania ma TransferMode
właściwość, którą można ustawić na Buffered
, Streamed
, StreamedRequest
lub StreamedResponse
. Ustawienie trybu transferu w celu Streamed
włączenia komunikacji przesyłanej strumieniowo w obu kierunkach. Ustawienie trybu transferu na StreamedRequest
lub StreamedResponse
umożliwia komunikację strumieniową tylko w żądaniu lub odpowiedzi, odpowiednio.
Właściwość basicHttpBinding
uwidacznia TransferMode
w powiązaniu tak jak NetTcpBinding
i NetNamedPipeBinding
. W przypadku innych transportów należy utworzyć niestandardowe powiązanie, aby ustawić tryb transferu.
Poniższy kod konfiguracji z przykładu pokazuje ustawienie TransferMode
właściwości na przesyłanie strumieniowe na basicHttpBinding
obiekcie i niestandardowe powiązanie HTTP:
<!-- An example basicHttpBinding using streaming. -->
<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>
Oprócz ustawienia na transferMode
Streamed
wartość , poprzedni kod konfiguracji ustawia maxReceivedMessageSize
wartość 64 MB. Jako mechanizm obrony umieszcza maxReceivedMessageSize
limit maksymalnego dozwolonego rozmiaru komunikatów odbieranych. Wartość domyślna maxReceivedMessageSize
to 64 KB, która zwykle jest zbyt mała w przypadku scenariuszy przesyłania strumieniowego.
Przetwarzanie danych przesyłanych strumieniowo
Operacje GetStream
i UploadStream
EchoStream
wszystkie dotyczą wysyłania danych bezpośrednio z pliku lub zapisywania odebranych danych bezpośrednio do pliku. Jednak w niektórych przypadkach istnieje wymóg wysyłania lub odbierania dużych ilości danych i wykonywania niektórych operacji przetwarzania na fragmentach danych podczas ich wysyłania lub odbierania. Jednym ze sposobów rozwiązania takich scenariuszy jest zapisanie strumienia niestandardowego (klasy pochodzącej z Streamklasy ), która przetwarza dane podczas ich odczytu lub zapisu. Przykład GetReversedStream
operacji i ReverseStream
klasy.
GetReversedStream
tworzy i zwraca nowe wystąpienie klasy ReverseStream
. Rzeczywiste przetwarzanie odbywa się, gdy system odczytuje z tego ReverseStream
obiektu. Implementacja ReverseStream.Read
odczytuje fragment bajtów z pliku bazowego, odwraca je, a następnie zwraca odwrócone bajty. Nie powoduje to odwrócenia całej zawartości pliku; odwraca jeden fragment bajtów naraz. Jest to przykład pokazujący, jak można wykonać przetwarzanie strumienia, ponieważ zawartość jest odczytywana lub zapisywana z i do strumienia.
class ReverseStream : Stream
{
FileStream inStream;
internal ReverseStream(string filePath)
{
//Opens the file and places a StreamReader around it.
inStream = File.OpenRead(filePath);
}
// Other methods removed for brevity.
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 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;
}
}
}
Uruchamianie przykładu
Aby uruchomić przykład, najpierw skompiluj usługę i klienta, postępując zgodnie z instrukcjami na końcu tego dokumentu. Następnie uruchom usługę i klienta w dwóch różnych oknach konsoli. Po uruchomieniu klienta czeka na naciśnięcie klawisza ENTER, gdy usługa będzie gotowa. Następnie klient wywołuje metody GetStream()
, UploadStream()
i GetReversedStream()
najpierw za pośrednictwem protokołu HTTP, a następnie za pośrednictwem protokołu TCP. Oto przykładowe dane wyjściowe z usługi, a następnie przykładowe dane wyjściowe z klienta:
Dane wyjściowe usługi:
The streaming service is ready.
Press <ENTER> to terminate service.
Saving to file D:\...\uploadedfile
......................
File D:\...\uploadedfile saved
Saving to file D:\...\uploadedfile
...............
File D:\...\uploadedfile saved
Dane wyjściowe klienta:
Press <ENTER> when service is ready
------ Using HTTP ------
Calling GetStream()
Saving to file D:\...\clientfile
......................
Wrote 33405 bytes to stream
File D:\...\clientfile saved
Calling UploadStream()
Calling GetReversedStream()
Saving to file D:\...\clientfile
......................
Wrote 33405 bytes to stream
File D:\...\clientfile saved
------ Using Custom HTTP ------
Calling GetStream()
Saving to file D:\...\clientfile
...............
Wrote 33405 bytes to stream
File D:\...\clientfile saved
Calling UploadStream()
Calling GetReversedStream()
Saving to file D:\...\clientfile
...............
Wrote 33405 bytes to stream
File D:\...\clientfile saved
Press <ENTER> to terminate client.
Aby skonfigurować, skompilować i uruchomić przykład
Upewnij się, że wykonano procedurę instalacji jednorazowej dla przykładów programu Windows Communication Foundation.
Aby skompilować wersję rozwiązania w języku C# lub Visual Basic .NET, postępuj zgodnie z instrukcjami w temacie Building the Windows Communication Foundation Samples (Tworzenie przykładów programu Windows Communication Foundation).
Aby uruchomić przykład w konfiguracji pojedynczej lub między maszynami, postępuj zgodnie z instrukcjami w temacie Uruchamianie przykładów programu Windows Communication Foundation.
Uwaga
Jeśli używasz Svcutil.exe do ponownego wygenerowania konfiguracji dla tego przykładu, pamiętaj o zmodyfikowaniu nazwy punktu końcowego w konfiguracji klienta, aby był zgodny z kodem klienta.