Notitie
Voor toegang tot deze pagina is autorisatie vereist. U kunt proberen u aan te melden of de directory te wijzigen.
Voor toegang tot deze pagina is autorisatie vereist. U kunt proberen de mappen te wijzigen.
WebSockets bieden een mechanisme voor snelle, veilige, tweerichtingscommunicatie tussen een client en een server via internet met behulp van HTTP(S) en ondersteuning voor zowel UTF-8- als binaire berichten.
Onder het WebSocket-protocol worden gegevens onmiddellijk overgedragen via een full-duplex single socket-verbinding, zodat berichten in realtime kunnen worden verzonden en ontvangen van beide eindpunten. WebSockets zijn ideaal voor gebruik in multiplayer gaming (zowel realtime als turn-based), directe sociale netwerkmeldingen, up-to-datumweergaven van voorraad- of weerinformatie, en andere apps die veilige en snelle gegevensoverdracht vereisen.
Om een WebSocket-verbinding tot stand te brengen, wordt een specifieke op HTTP gebaseerde handshake uitgewisseld tussen de client en de server. Als dit lukt, wordt het protocol voor de toepassingslaag bijgewerkt van HTTP naar WebSockets, met behulp van de eerder tot stand gebrachte TCP-verbinding. Zodra dit gebeurt, is HTTP volledig uit de afbeelding; gegevens kunnen worden verzonden of ontvangen met behulp van het WebSocket-protocol door beide eindpunten, totdat de WebSocket-verbinding is gesloten.
Opmerking Een client kan WebSockets niet gebruiken om gegevens over te dragen, tenzij de server ook gebruikmaakt van het WebSocket-protocol. Als de server geen ondersteuning biedt voor WebSockets, moet u een andere methode voor gegevensoverdracht gebruiken.
Windows biedt ondersteuning voor zowel client- als servergebruik van WebSockets. De Windows. Networking.Sockets-naamruimte definieert twee WebSocket-klassen voor gebruik door clients: MessageWebSocket en StreamWebSocket. Hier volgt een vergelijking van deze twee WebSocket-klassen.
| MessageWebSocket | StreamWebSocket |
|---|---|
| Een volledig WebSocket-bericht wordt in één bewerking gelezen/geschreven. | Secties van een bericht kunnen worden gelezen met elke leesbewerking. |
| Geschikt wanneer berichten niet erg groot zijn. | Geschikt wanneer zeer grote bestanden (zoals foto's of video's) worden overgebracht. |
| Ondersteunt zowel UTF-8- als binaire berichten. | Ondersteunt alleen binaire berichten. |
| Vergelijkbaar met een UDP- of datagramsocket (in de zin dat het bedoeld is voor frequente, kleine berichten), maar met de betrouwbaarheid van TCP, garanties voor pakketorders en congestiebeheer. | Vergelijkbaar met een TCP- of streamsocket. |
Uw verbinding beveiligen met TLS/SSL
In de meeste gevallen wilt u een beveiligde WebSocket-verbinding gebruiken, zodat de gegevens die u verzendt en ontvangt, worden versleuteld. Dit vergroot ook de kans dat uw verbinding slaagt, omdat veel tussenpersonen, zoals firewalls en proxy's, niet-versleutelde WebSocket-verbindingen weigeren. Het WebSocket-protocol definieert deze twee URI-schema's.
| URI-schema | Purpose |
|---|---|
| Wss: | Gebruik deze optie voor beveiligde verbindingen die moeten worden versleuteld. |
| Ws: | Gebruiken voor niet-versleutelde verbindingen. |
Gebruik het wss: URI-schema om uw WebSocket-verbinding te versleutelen. Dit is een voorbeeld.
protected override async void OnNavigatedTo(NavigationEventArgs e)
{
var webSocket = new Windows.Networking.Sockets.MessageWebSocket();
await webSocket.ConnectAsync(new Uri("wss://www.contoso.com/mywebservice"));
}
#include <winrt/Windows.Foundation.h>
#include <winrt/Windows.Networking.Sockets.h>
#include <sstream>
using namespace winrt;
using namespace Windows::Foundation;
...
IAsyncAction ConnectWebSocketAsync()
{
Windows::Networking::Sockets::MessageWebSocket webSocket;
co_await webSocket.ConnectAsync(Uri{ L"wss://www.contoso.com/mywebservice" });
}
MessageWebSocket gebruiken om verbinding te maken
Met MessageWebSocket kan een volledig WebSocket-bericht in één bewerking worden gelezen/geschreven. Daarom is het geschikt wanneer berichten niet erg groot zijn. De klasse ondersteunt zowel UTF-8- als binaire berichten.
De onderstaande voorbeeldcode maakt verbinding met een WebSocket-server en verzendt een bericht. De openbare echo.websocket.org service wordt stopgezet, dus vervang de tijdelijke aanduidings-URI in deze voorbeelden door uw eigen WebSocket-server-URI.
private Windows.Networking.Sockets.MessageWebSocket messageWebSocket;
protected override void OnNavigatedTo(NavigationEventArgs e)
{
this.messageWebSocket = new Windows.Networking.Sockets.MessageWebSocket();
// In this example, we send/receive a string, so we need to set the MessageType to Utf8.
this.messageWebSocket.Control.MessageType = Windows.Networking.Sockets.SocketMessageType.Utf8;
this.messageWebSocket.MessageReceived += WebSocket_MessageReceived;
this.messageWebSocket.Closed += WebSocket_Closed;
try
{
// Replace with your WebSocket server URI.
Task connectTask = this.messageWebSocket.ConnectAsync(new Uri("wss://example.com/ws")).AsTask();
connectTask.ContinueWith(_ => this.SendMessageUsingMessageWebSocketAsync("Hello, World!"));
}
catch (Exception ex)
{
Windows.Web.WebErrorStatus webErrorStatus = Windows.Networking.Sockets.WebSocketError.GetStatus(ex.GetBaseException().HResult);
// Add additional code here to handle exceptions.
}
}
private async Task SendMessageUsingMessageWebSocketAsync(string message)
{
using (var dataWriter = new DataWriter(this.messageWebSocket.OutputStream))
{
dataWriter.WriteString(message);
await dataWriter.StoreAsync();
dataWriter.DetachStream();
}
Debug.WriteLine("Sending message using MessageWebSocket: " + message);
}
private void WebSocket_MessageReceived(Windows.Networking.Sockets.MessageWebSocket sender, Windows.Networking.Sockets.MessageWebSocketMessageReceivedEventArgs args)
{
try
{
using (DataReader dataReader = args.GetDataReader())
{
dataReader.UnicodeEncoding = Windows.Storage.Streams.UnicodeEncoding.Utf8;
string message = dataReader.ReadString(dataReader.UnconsumedBufferLength);
Debug.WriteLine("Message received from MessageWebSocket: " + message);
this.messageWebSocket.Dispose();
}
}
catch (Exception ex)
{
Windows.Web.WebErrorStatus webErrorStatus = Windows.Networking.Sockets.WebSocketError.GetStatus(ex.GetBaseException().HResult);
// Add additional code here to handle exceptions.
}
}
private void WebSocket_Closed(Windows.Networking.Sockets.IWebSocket sender, Windows.Networking.Sockets.WebSocketClosedEventArgs args)
{
Debug.WriteLine("WebSocket_Closed; Code: " + args.Code + ", Reason: \"" + args.Reason + "\"");
// Add additional code here to handle the WebSocket being closed.
}
#include <winrt/Windows.Foundation.h>
#include <winrt/Windows.Networking.Sockets.h>
#include <winrt/Windows.Storage.Streams.h>
#include <winrt/Microsoft.UI.Xaml.Navigation.h>
#include <sstream>
using namespace winrt;
using namespace Windows::Foundation;
using namespace Windows::Storage::Streams;
using namespace Windows::UI::Xaml::Navigation;
...
private:
Windows::Networking::Sockets::MessageWebSocket m_messageWebSocket;
winrt::event_token m_messageReceivedEventToken;
winrt::event_token m_closedEventToken;
public:
IAsyncAction OnNavigatedTo(NavigationEventArgs /* e */)
{
// In this example, we send/receive a string, so we need to set the MessageType to Utf8.
m_messageWebSocket.Control().MessageType(Windows::Networking::Sockets::SocketMessageType::Utf8);
m_messageReceivedEventToken = m_messageWebSocket.MessageReceived({ this, &MessageWebSocketPage::OnWebSocketMessageReceived });
m_closedEventToken = m_messageWebSocket.Closed({ this, &MessageWebSocketPage::OnWebSocketClosed });
try
{
co_await m_messageWebSocket.ConnectAsync(Uri{ L"wss://example.com/ws" });
SendMessageUsingMessageWebSocketAsync(L"Hello, World!");
}
catch (winrt::hresult_error const& ex)
{
Windows::Web::WebErrorStatus webErrorStatus{ Windows::Networking::Sockets::WebSocketError::GetStatus(ex.to_abi()) };
// Add additional code here to handle exceptions.
}
}
private:
IAsyncAction SendMessageUsingMessageWebSocketAsync(std::wstring message)
{
DataWriter dataWriter{ m_messageWebSocket.OutputStream() };
dataWriter.WriteString(message);
co_await dataWriter.StoreAsync();
dataWriter.DetachStream();
std::wstringstream wstringstream;
wstringstream << L"Sending message using MessageWebSocket: " << message.c_str() << std::endl;
::OutputDebugString(wstringstream.str().c_str());
}
void OnWebSocketMessageReceived(Windows::Networking::Sockets::MessageWebSocket const& /* sender */, Windows::Networking::Sockets::MessageWebSocketMessageReceivedEventArgs const& args)
{
try
{
DataReader dataReader{ args.GetDataReader() };
dataReader.UnicodeEncoding(Windows::Storage::Streams::UnicodeEncoding::Utf8);
auto message = dataReader.ReadString(dataReader.UnconsumedBufferLength());
std::wstringstream wstringstream;
wstringstream << L"Message received from MessageWebSocket: " << message.c_str() << std::endl;
::OutputDebugString(wstringstream.str().c_str());
m_messageWebSocket.Close(1000, L"");
}
catch (winrt::hresult_error const& ex)
{
Windows::Web::WebErrorStatus webErrorStatus{ Windows::Networking::Sockets::WebSocketError::GetStatus(ex.to_abi()) };
// Add additional code here to handle exceptions.
}
}
void OnWebSocketClosed(Windows::Networking::Sockets::IWebSocket const& /* sender */, Windows::Networking::Sockets::WebSocketClosedEventArgs const& args)
{
std::wstringstream wstringstream;
wstringstream << L"WebSocket_Closed; Code: " << args.Code() << ", Reason: \"" << args.Reason().c_str() << "\"" << std::endl;
::OutputDebugString(wstringstream.str().c_str());
// Add additional code here to handle the WebSocket being closed.
}
#include <ppltasks.h>
#include <sstream>
...
using namespace Windows::Foundation;
using namespace Windows::Storage::Streams;
using namespace Windows::UI::Xaml::Navigation;
...
private:
Windows::Networking::Sockets::MessageWebSocket^ messageWebSocket;
protected:
virtual void OnNavigatedTo(NavigationEventArgs^ e) override
{
this->messageWebSocket = ref new Windows::Networking::Sockets::MessageWebSocket();
// In this example, we send/receive a string, so we need to set the MessageType to Utf8.
this->messageWebSocket->Control->MessageType = Windows::Networking::Sockets::SocketMessageType::Utf8;
this->messageWebSocket->MessageReceived += ref new TypedEventHandler<Windows::Networking::Sockets::MessageWebSocket^, Windows::Networking::Sockets::MessageWebSocketMessageReceivedEventArgs^>(this, &MessageWebSocketPage::WebSocket_MessageReceived);
this->messageWebSocket->Closed += ref new TypedEventHandler<Windows::Networking::Sockets::IWebSocket^, Windows::Networking::Sockets::WebSocketClosedEventArgs^>(this, &MessageWebSocketPage::WebSocket_Closed);
try
{
auto connectTask = Concurrency::create_task(this->messageWebSocket->ConnectAsync(ref new Uri(L"wss://example.com/ws")));
connectTask.then([this] { this->SendMessageUsingMessageWebSocketAsync(L"Hello, World!"); });
}
catch (Platform::Exception^ ex)
{
Windows::Web::WebErrorStatus webErrorStatus = Windows::Networking::Sockets::WebSocketError::GetStatus(ex->HResult);
// Add additional code here to handle exceptions.
}
}
private:
void SendMessageUsingMessageWebSocketAsync(Platform::String^ message)
{
auto dataWriter = ref new DataWriter(this->messageWebSocket->OutputStream);
dataWriter->WriteString(message);
Concurrency::create_task(dataWriter->StoreAsync()).then(
[=](unsigned int)
{
dataWriter->DetachStream();
std::wstringstream wstringstream;
wstringstream << L"Sending message using MessageWebSocket: " << message->Data() << std::endl;
::OutputDebugString(wstringstream.str().c_str());
});
}
void WebSocket_MessageReceived(Windows::Networking::Sockets::MessageWebSocket^ sender, Windows::Networking::Sockets::MessageWebSocketMessageReceivedEventArgs^ args)
{
try
{
DataReader^ dataReader = args->GetDataReader();
dataReader->UnicodeEncoding = Windows::Storage::Streams::UnicodeEncoding::Utf8;
Platform::String^ message = dataReader->ReadString(dataReader->UnconsumedBufferLength);
std::wstringstream wstringstream;
wstringstream << L"Message received from MessageWebSocket: " << message->Data() << std::endl;
::OutputDebugString(wstringstream.str().c_str());
this->messageWebSocket->Close(1000, L"");
}
catch (Platform::Exception^ ex)
{
Windows::Web::WebErrorStatus webErrorStatus = Windows::Networking::Sockets::WebSocketError::GetStatus(ex->HResult);
// Add additional code here to handle exceptions.
}
}
void WebSocket_Closed(Windows::Networking::Sockets::IWebSocket^ sender, Windows::Networking::Sockets::WebSocketClosedEventArgs^ args)
{
std::wstringstream wstringstream;
wstringstream << L"WebSocket_Closed; Code: " << args->Code << ", Reason: \"" << args->Reason->Data() << "\"" << std::endl;
::OutputDebugString(wstringstream.str().c_str());
// Add additional code here to handle the WebSocket being closed.
}
De gebeurtenissen MessageWebSocket.MessageReceived en MessageWebSocket.Closed afhandelen
Zoals u in het bovenstaande voorbeeld ziet, moet u zich abonneren op de gebeurtenissen MessageWebSocket.MessageReceived en MessageWebSocket.Closed voordat u verbinding maakt en gegevens verzendt met een MessageWebSocket.
MessageReceived wordt gegenereerd wanneer gegevens worden ontvangen. De gegevens zijn toegankelijk via MessageWebSocketMessageReceivedEventArgs. Gesloten wordt gegenereerd wanneer de client of de server de socket sluit.
Gegevens verzenden op een MessageWebSocket
Zodra een verbinding tot stand is gebracht, kunt u gegevens naar de server verzenden. U doet dit door de eigenschap MessageWebSocket.OutputStream en een DataWriter te gebruiken om de gegevens te schrijven.
Opmerking De DataWriter is eigenaar van de uitvoerstroom. Wanneer de DataWriter buiten de scope valt, geeft de DataWriter, als de uitvoerstroom eraan is gekoppeld, de uitvoerstroom vrij. Daarna mislukken volgende pogingen om de uitvoerstroom te gebruiken met een HRESULT-waarde van 0x80000013. Maar u kunt DataWriter.DetachStream aanroepen om de uitvoerstroom los te koppelen van de DataWriter en het eigendom van de stream terug te sturen naar de MessageWebSocket.
StreamWebSocket gebruiken om verbinding te maken
Met StreamWebSocket kunnen secties van een bericht worden gelezen met elke leesbewerking. Daarom is het geschikt wanneer zeer grote bestanden (zoals foto's of video's) worden overgedragen. De klasse ondersteunt alleen binaire berichten.
De onderstaande voorbeeldcode maakt verbinding met een WebSocket-server en verzendt een bericht. De openbare echo.websocket.org service wordt stopgezet, dus in deze voorbeelden wordt ook een tijdelijke URI gebruikt die u moet vervangen door uw eigen WebSocket-server-URI.
private Windows.Networking.Sockets.StreamWebSocket streamWebSocket;
protected override void OnNavigatedTo(NavigationEventArgs e)
{
this.streamWebSocket = new Windows.Networking.Sockets.StreamWebSocket();
this.streamWebSocket.Closed += WebSocket_Closed;
try
{
Task connectTask = this.streamWebSocket.ConnectAsync(new Uri("wss://example.com/ws")).AsTask();
connectTask.ContinueWith(_ =>
{
Task.Run(() => this.ReceiveMessageUsingStreamWebSocket());
Task.Run(() => this.SendMessageUsingStreamWebSocket(new byte[] { 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09 }));
});
}
catch (Exception ex)
{
Windows.Web.WebErrorStatus webErrorStatus = Windows.Networking.Sockets.WebSocketError.GetStatus(ex.GetBaseException().HResult);
// Add code here to handle exceptions.
}
}
private async void ReceiveMessageUsingStreamWebSocket()
{
try
{
using (var dataReader = new DataReader(this.streamWebSocket.InputStream))
{
dataReader.InputStreamOptions = InputStreamOptions.Partial;
await dataReader.LoadAsync(256);
byte[] message = new byte[dataReader.UnconsumedBufferLength];
dataReader.ReadBytes(message);
Debug.WriteLine("Data received from StreamWebSocket: " + message.Length + " bytes");
}
this.streamWebSocket.Dispose();
}
catch (Exception ex)
{
Windows.Web.WebErrorStatus webErrorStatus = Windows.Networking.Sockets.WebSocketError.GetStatus(ex.GetBaseException().HResult);
// Add code here to handle exceptions.
}
}
private async void SendMessageUsingStreamWebSocket(byte[] message)
{
try
{
using (var dataWriter = new DataWriter(this.streamWebSocket.OutputStream))
{
dataWriter.WriteBytes(message);
await dataWriter.StoreAsync();
dataWriter.DetachStream();
}
Debug.WriteLine("Sending data using StreamWebSocket: " + message.Length.ToString() + " bytes");
}
catch (Exception ex)
{
Windows.Web.WebErrorStatus webErrorStatus = Windows.Networking.Sockets.WebSocketError.GetStatus(ex.GetBaseException().HResult);
// Add code here to handle exceptions.
}
}
private void WebSocket_Closed(Windows.Networking.Sockets.IWebSocket sender, Windows.Networking.Sockets.WebSocketClosedEventArgs args)
{
Debug.WriteLine("WebSocket_Closed; Code: " + args.Code + ", Reason: \"" + args.Reason + "\"");
// Add additional code here to handle the WebSocket being closed.
}
#include <winrt/Windows.Foundation.h>
#include <winrt/Windows.Networking.Sockets.h>
#include <winrt/Windows.Storage.Streams.h>
#include <winrt/Microsoft.UI.Xaml.Navigation.h>
#include <sstream>
using namespace winrt;
using namespace Windows::Foundation;
using namespace Windows::Storage::Streams;
using namespace Windows::UI::Xaml::Navigation;
...
private:
Windows::Networking::Sockets::StreamWebSocket m_streamWebSocket;
winrt::event_token m_closedEventToken;
public:
IAsyncAction OnNavigatedTo(NavigationEventArgs /* e */)
{
m_closedEventToken = m_streamWebSocket.Closed({ this, &StreamWebSocketPage::OnWebSocketClosed });
try
{
co_await m_streamWebSocket.ConnectAsync(Uri{ L"wss://example.com/ws" });
ReceiveMessageUsingStreamWebSocket();
SendMessageUsingStreamWebSocket({ 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09 });
}
catch (winrt::hresult_error const& ex)
{
Windows::Web::WebErrorStatus webErrorStatus{ Windows::Networking::Sockets::WebSocketError::GetStatus(ex.to_abi()) };
// Add additional code here to handle exceptions.
}
}
private:
IAsyncAction SendMessageUsingStreamWebSocket(std::vector< byte > message)
{
try
{
DataWriter dataWriter{ m_streamWebSocket.OutputStream() };
dataWriter.WriteBytes(message);
co_await dataWriter.StoreAsync();
dataWriter.DetachStream();
std::wstringstream wstringstream;
wstringstream << L"Sending data using StreamWebSocket: " << message.size() << L" bytes" << std::endl;
::OutputDebugString(wstringstream.str().c_str());
}
catch (winrt::hresult_error const& ex)
{
Windows::Web::WebErrorStatus webErrorStatus{ Windows::Networking::Sockets::WebSocketError::GetStatus(ex.to_abi()) };
// Add additional code here to handle exceptions.
}
}
IAsyncAction ReceiveMessageUsingStreamWebSocket()
{
try
{
DataReader dataReader{ m_streamWebSocket.InputStream() };
dataReader.InputStreamOptions(InputStreamOptions::Partial);
unsigned int bytesLoaded = co_await dataReader.LoadAsync(256);
std::vector< byte > message(bytesLoaded);
dataReader.ReadBytes(message);
std::wstringstream wstringstream;
wstringstream << L"Data received from StreamWebSocket: " << message.size() << " bytes" << std::endl;
::OutputDebugString(wstringstream.str().c_str());
m_streamWebSocket.Close(1000, L"");
}
catch (winrt::hresult_error const& ex)
{
Windows::Web::WebErrorStatus webErrorStatus{ Windows::Networking::Sockets::WebSocketError::GetStatus(ex.to_abi()) };
// Add additional code here to handle exceptions.
}
}
void OnWebSocketClosed(Windows::Networking::Sockets::IWebSocket const&, Windows::Networking::Sockets::WebSocketClosedEventArgs const& args)
{
std::wstringstream wstringstream;
wstringstream << L"WebSocket_Closed; Code: " << args.Code() << ", Reason: \"" << args.Reason().c_str() << "\"" << std::endl;
::OutputDebugString(wstringstream.str().c_str());
// Add additional code here to handle the WebSocket being closed.
}
#include <ppltasks.h>
#include <sstream>
...
using namespace Windows::Foundation;
using namespace Windows::Storage::Streams;
using namespace Windows::UI::Xaml::Navigation;
...
private:
Windows::Networking::Sockets::StreamWebSocket^ streamWebSocket;
protected:
virtual void OnNavigatedTo(NavigationEventArgs^ e) override
{
this->streamWebSocket = ref new Windows::Networking::Sockets::StreamWebSocket();
this->streamWebSocket->Closed += ref new TypedEventHandler<Windows::Networking::Sockets::IWebSocket^, Windows::Networking::Sockets::WebSocketClosedEventArgs^>(this, &StreamWebSocketPage::WebSocket_Closed);
try
{
auto connectTask = Concurrency::create_task(this->streamWebSocket->ConnectAsync(ref new Uri(L"wss://example.com/ws")));
connectTask.then(
[=]
{
this->ReceiveMessageUsingStreamWebSocket();
this->SendMessageUsingStreamWebSocket(ref new Platform::Array< byte >{ 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09 });
});
}
catch (Platform::Exception^ ex)
{
Windows::Web::WebErrorStatus webErrorStatus = Windows::Networking::Sockets::WebSocketError::GetStatus(ex->HResult);
// Add additional code here to handle exceptions.
}
}
private:
void SendMessageUsingStreamWebSocket(const Platform::Array< byte >^ message)
{
try
{
auto dataWriter = ref new DataWriter(this->streamWebSocket->OutputStream);
dataWriter->WriteBytes(message);
Concurrency::create_task(dataWriter->StoreAsync()).then(
[=](Concurrency::task< unsigned int >) // task< unsigned int > instead of unsigned int in order to handle any exceptions thrown in StoreAsync().
{
dataWriter->DetachStream();
std::wstringstream wstringstream;
wstringstream << L"Sending data using StreamWebSocket: " << message->Length << L" bytes" << std::endl;
::OutputDebugString(wstringstream.str().c_str());
});
}
catch (Platform::Exception^ ex)
{
Windows::Web::WebErrorStatus webErrorStatus = Windows::Networking::Sockets::WebSocketError::GetStatus(ex->HResult);
// Add additional code here to handle exceptions.
}
}
void ReceiveMessageUsingStreamWebSocket()
{
try
{
DataReader^ dataReader = ref new DataReader(this->streamWebSocket->InputStream);
dataReader->InputStreamOptions = InputStreamOptions::Partial;
Concurrency::create_task(dataReader->LoadAsync(256)).then(
[=](unsigned int bytesLoaded)
{
auto message = ref new Platform::Array< byte >(bytesLoaded);
dataReader->ReadBytes(message);
std::wstringstream wstringstream;
wstringstream << L"Data received from StreamWebSocket: " << message->Length << " bytes" << std::endl;
::OutputDebugString(wstringstream.str().c_str());
this->streamWebSocket->Close(1000, L"");
});
}
catch (Platform::Exception^ ex)
{
Windows::Web::WebErrorStatus webErrorStatus = Windows::Networking::Sockets::WebSocketError::GetStatus(ex->HResult);
// Add additional code here to handle exceptions.
}
}
void WebSocket_Closed(Windows::Networking::Sockets::IWebSocket^ sender, Windows::Networking::Sockets::WebSocketClosedEventArgs^ args)
{
std::wstringstream wstringstream;
wstringstream << L"WebSocket_Closed; Code: " << args->Code << ", Reason: \"" << args->Reason->Data() << "\"" << std::endl;
::OutputDebugString(wstringstream.str().c_str());
// Add additional code here to handle the WebSocket being closed.
}
De gebeurtenis StreamWebSocket.Closed afhandelen
Voordat u verbinding maakt en gegevens verzendt met een StreamWebSocket, moet u zich abonneren op de gebeurtenis StreamWebSocket.Closed . Gesloten wordt gegenereerd wanneer de client of de server de socket sluit.
Gegevens verzenden in een StreamWebSocket
Zodra een verbinding tot stand is gebracht, kunt u gegevens naar de server verzenden. U doet dit met behulp van de eigenschap StreamWebSocket.OutputStream en een DataWriter om de gegevens te schrijven.
Opmerking Als u meer gegevens op dezelfde socket wilt schrijven, moet u DataWriter.DetachStream aanroepen om de uitvoerstroom van de DataWriter los te koppelen voordat de DataWriter buiten het bereik komt. Hiermee wordt het eigendom van de stream naar de StreamWebSocket geretourneerd.
Gegevens ontvangen op een StreamWebSocket
Gebruik de eigenschap StreamWebSocket.InputStream en een DataReader om de gegevens te lezen.
Geavanceerde opties voor MessageWebSocket en StreamWebSocket
Voordat u een verbinding tot stand kunt brengen, kunt u geavanceerde opties voor een socket instellen door eigenschappen in te stellen op MessageWebSocketControl of StreamWebSocketControl. U opent een exemplaar van deze klassen vanuit het socketobject zelf via de eigenschap MessageWebSocket.Control of de eigenschap StreamWebSocket.Control , indien van toepassing.
Hier volgt een voorbeeld met StreamWebSocket. Hetzelfde patroon is van toepassing op MessageWebSocket.
var streamWebSocket = new Windows.Networking.Sockets.StreamWebSocket();
// By default, the Nagle algorithm is not used. This overrides that, and causes it to be used.
streamWebSocket.Control.NoDelay = false;
await streamWebSocket.ConnectAsync(new Uri("wss://example.com/ws"));
Windows::Networking::Sockets::StreamWebSocket streamWebSocket;
// By default, the Nagle algorithm is not used. This overrides that, and causes it to be used.
streamWebSocket.Control().NoDelay(false);
auto connectAsyncAction = streamWebSocket.ConnectAsync(Uri{ L"wss://example.com/ws" });
auto streamWebSocket = ref new Windows::Networking::Sockets::StreamWebSocket();
// By default, the Nagle algorithm is not used. This overrides that, and causes it to be used.
streamWebSocket->Control->NoDelay = false;
auto connectTask = Concurrency::create_task(streamWebSocket->ConnectAsync(ref new Uri(L"wss://example.com/ws")));
Opmerking Probeer geen besturingselementeigenschap te wijzigen nadat u ConnectAsync hebt aangeroepen. De enige uitzondering op die regel is MessageWebSocketControl.MessageType.
WebSocket-informatieklassen
MessageWebSocket en StreamWebSocket hebben elk een bijbehorende klasse die aanvullende informatie over het object biedt.
MessageWebSocketInformation biedt informatie over een MessageWebSocket en u haalt een exemplaar ervan op met behulp van de eigenschap MessageWebSocket.Information .
StreamWebSocketInformation biedt informatie over een StreamWebSocket en u haalt een exemplaar ervan op met behulp van de eigenschap StreamWebSocket.Information .
Houd er rekening mee dat de eigenschappen van deze informatieklassen alleen-lezen zijn, maar u kunt ze op elk gewenst moment gebruiken om gegevens op te halen tijdens de levensduur van een websocketobject.
Afhandeling van uitzonderingen
Een fout die optreedt bij een MessageWebSocket- of StreamWebSocket-bewerking, wordt als HRESULT-waarde geretourneerd. U kunt die HRESULT-waarde doorgeven aan de methode WebSocketError.GetStatus om deze te converteren naar een opsommingswaarde webErrorStatus .
De meeste opsommingswaarden van WebErrorStatus komen overeen met een fout die wordt geretourneerd door de systeemeigen HTTP-clientbewerking. Uw app kan de opsommingswaarden webErrorStatus inschakelen om het gedrag van apps te wijzigen, afhankelijk van de oorzaak van de uitzondering.
Voor parametervalidatiefouten kunt u HRESULT van de uitzondering gebruiken voor meer gedetailleerde informatie over de fout. Mogelijke HRESULT-waarden worden vermeld in Winerror.h, die u kunt vinden in uw SDK-installatie (bijvoorbeeld in de map C:\Program Files (x86)\Windows Kits\10\Include\<VERSION>\shared). Voor de meeste parametervalidatiefouten is de geretourneerde HRESULTE_INVALIDARG.
Time-outs instellen voor WebSocket-bewerkingen
MessageWebSocket en StreamWebSocket gebruiken een interne systeemservice voor het verzenden van WebSocket-clientaanvragen en het ontvangen van reacties van een server. De standaardtime-outwaarde die wordt gebruikt voor een WebSocket-verbindingsbewerking is 60 seconden. Als de HTTP-server die WebSockets ondersteunt niet of niet kan reageren op de webSocket-verbindingsaanvraag (deze is tijdelijk offline of geblokkeerd door een netwerkstoring), wacht de interne systeemservice de standaard 60 seconden voordat er een fout wordt geretourneerd. Deze fout zorgt ervoor dat er een uitzondering wordt gegenereerd in de methode WebSocket ConnectAsync . Voor verzend- en ontvangstbewerkingen nadat een WebSocket-verbinding tot stand is gebracht, is de standaardtime-out 30 seconden.
Als de naamquery voor een HTTP-servernaam in de URI meerdere IP-adressen voor de naam retourneert, probeert de interne systeemservice maximaal 5 IP-adressen voor de site (elk met een standaardtime-out van 60 seconden) voordat deze mislukt. Daarom kan uw app enkele minuten wachten om verbinding te maken met meerdere IP-adressen voordat er een uitzondering wordt verwerkt. Dit gedrag kan voor de gebruiker lijken alsof de app niet meer werkt.
Als u uw app sneller wilt laten reageren en deze problemen wilt minimaliseren, kunt u een kortere time-out instellen voor verbindingsaanvragen. U stelt een time-out op een vergelijkbare manier in voor zowel MessageWebSocket als StreamWebSocket.
private Windows.Networking.Sockets.MessageWebSocket messageWebSocket;
protected override void OnNavigatedTo(NavigationEventArgs e)
{
this.messageWebSocket = new Windows.Networking.Sockets.MessageWebSocket();
try
{
var cancellationTokenSource = new CancellationTokenSource();
var connectTask = this.messageWebSocket.ConnectAsync(new Uri("wss://example.com/ws")).AsTask(cancellationTokenSource.Token);
// Cancel connectTask after 5 seconds.
cancellationTokenSource.CancelAfter(TimeSpan.FromMilliseconds(5000));
connectTask.ContinueWith((antecedent) =>
{
if (antecedent.Status == TaskStatus.RanToCompletion)
{
// connectTask ran to completion, so we know that the MessageWebSocket is connected.
// Add additional code here to use the MessageWebSocket.
}
else
{
// connectTask timed out, or faulted.
}
});
}
catch (Exception ex)
{
Windows.Web.WebErrorStatus webErrorStatus = Windows.Networking.Sockets.WebSocketError.GetStatus(ex.GetBaseException().HResult);
// Add additional code here to handle exceptions.
}
}
#include <winrt/Windows.Foundation.h>
#include <winrt/Windows.Networking.Sockets.h>
#include <winrt/Microsoft.UI.Xaml.Navigation.h>
#include <sstream>
using namespace winrt;
using namespace Windows::Foundation;
using namespace Windows::UI::Xaml::Navigation;
...
private:
Windows::Networking::Sockets::MessageWebSocket m_messageWebSocket;
IAsyncAction TimeoutAsync()
{
// Return control to the caller, and resume again to complete the async action after the timeout period.
// 5 seconds, in this example.
co_await(std::chrono::seconds{ 5 });
}
public:
IAsyncAction OnNavigatedTo(NavigationEventArgs /* e */)
{
try
{
// Return control to the caller, and then immediately resume on a thread pool thread.
co_await winrt::resume_background();
auto connectAsyncAction = m_messageWebSocket.ConnectAsync(Uri{ L"wss://example.com/ws" });
TimeoutAsync().Completed([connectAsyncAction](IAsyncAction const& sender, AsyncStatus const)
{
// TimeoutAsync completes after the timeout period. After that period, it's safe
// to cancel the ConnectAsync action even if it has already completed.
connectAsyncAction.Cancel();
});
try
{
// Block until the ConnectAsync action completes or is canceled.
connectAsyncAction.get();
}
catch (winrt::hresult_error const& ex)
{
std::wstringstream wstringstream;
wstringstream << L"ConnectAsync threw an exception: " << ex.message().c_str() << std::endl;
::OutputDebugString(wstringstream.str().c_str());
}
if (connectAsyncAction.Status() == AsyncStatus::Completed)
{
// connectTask ran to completion, so we know that the MessageWebSocket is connected.
// Add additional code here to use the MessageWebSocket.
}
else
{
// connectTask did not run to completion.
}
}
catch (winrt::hresult_error const& ex)
{
Windows::Web::WebErrorStatus webErrorStatus{ Windows::Networking::Sockets::WebSocketError::GetStatus(ex.to_abi()) };
// Add additional code here to handle exceptions.
}
}
#include <agents.h>
#include <ppltasks.h>
#include <sstream>
...
using namespace Windows::Foundation;
using namespace Windows::Storage::Streams;
using namespace Windows::UI::Xaml::Navigation;
...
private:
Windows::Networking::Sockets::MessageWebSocket^ messageWebSocket;
protected:
virtual void OnNavigatedTo(NavigationEventArgs^ e) override
{
this->messageWebSocket = ref new Windows::Networking::Sockets::MessageWebSocket();
try
{
Concurrency::cancellation_token_source cancellationTokenSource;
Concurrency::cancellation_token cancellationToken = cancellationTokenSource.get_token();
auto connectTask = Concurrency::create_task(this->messageWebSocket->ConnectAsync(ref new Uri(L"wss://example.com/ws")), cancellationToken);
// This continuation task returns true should connectTask run to completion.
Concurrency::task< bool > taskRanToCompletion = connectTask.then([](void)
{
return true;
});
// This task returns false after the specified timeout. 5 seconds, in this example.
Concurrency::task< bool > taskTimedout = Concurrency::create_task([]() -> bool
{
Concurrency::task_completion_event< void > taskCompletionEvent;
// A call object that sets the task completion event.
auto call = std::make_shared< Concurrency::call< int > >([taskCompletionEvent](int)
{
taskCompletionEvent.set();
});
// A non-repeating timer that calls the call object when the timer fires.
auto nonRepeatingTimer = std::make_shared< Concurrency::timer < int > >(5000, 0, call.get(), false);
nonRepeatingTimer->start();
// A task that completes after the completion event is set.
Concurrency::task< void > taskWaitForCompletionEvent(taskCompletionEvent);
return taskWaitForCompletionEvent.then([]() {return false; }).get();
});
(taskRanToCompletion || taskTimedout).then([this, cancellationTokenSource](bool connectTaskRanToCompletion)
{
if (connectTaskRanToCompletion)
{
// connectTask ran to completion, so we know that the MessageWebSocket is connected.
// Add additional code here to use the MessageWebSocket.
}
else
{
// taskTimedout ran to completion, so we should cancel connectTask via the cancellation_token_source.
cancellationTokenSource.cancel();
}
});
}
catch (Platform::Exception^ ex)
{
Windows::Web::WebErrorStatus webErrorStatus = Windows::Networking::Sockets::WebSocketError::GetStatus(ex->HResult);
// Add additional code here to handle exceptions.
}
}
Belangrijke API's
- DataReader
- DataWriter
- DataWriter.DetachStream
- MessageWebSocket
- MessageWebSocket.Closed
- MessageWebSocket.ConnectAsync
- MessageWebSocket.Control
- MessageWebSocket.Information
- MessageWebSocket.MessageReceived
- MessageWebSocket.OutputStream
- MessageWebSocketControl
- MessageWebSocketControl.MessageType
- MessageWebSocketInformation
- MessageWebSocketMessageReceivedEventArgs
- SocketMessageType
- StreamWebSocket
- StreamWebSocket.Closed
- StreamSocket.ConnectAsync
- StreamWebSocket.Control
- StreamWebSocket.Information
- StreamWebSocket.InputStream
- StreamWebSocket.OutputStream
- StreamWebSocketControl
- StreamWebSocketInformation
- WebErrorStatus
- WebSocketError.GetStatus
- Windows. Networking.Sockets
Verwante onderwerpen
Samples
Windows developer