Notatka
Dostęp do tej strony wymaga autoryzacji. Może spróbować zalogować się lub zmienić katalogi.
Dostęp do tej strony wymaga autoryzacji. Możesz spróbować zmienić katalogi.
Czynności, które należy wykonać dla dowolnej aplikacji z obsługą sieci.
Capabilities
Aby korzystać z sieci, należy dodać odpowiednie elementy możliwości do manifestu aplikacji. Jeśli w manifeście aplikacji nie zostanie określona żadna funkcja sieciowa, aplikacja nie będzie mieć możliwości sieci, a próba nawiązania połączenia z siecią zakończy się niepowodzeniem.
Poniżej przedstawiono najczęściej używane możliwości sieciowe.
| Capability | Opis |
|---|---|
| InternetClient | Zapewnia dostęp wychodzący do Internetu i sieci w miejscach publicznych, takich jak lotniska i kawiarnie. Większość aplikacji wymagających dostępu do Internetu powinna korzystać z tej możliwości. |
| InternetClientServer | Zapewnia aplikacji przychodzący i wychodzący dostęp do sieci z Internetu oraz sieci publicznych, takich jak te w portach lotniczych i kawiarniach. |
| privateNetworkClientServer | Zapewnia aplikacji przychodzący i wychodzący dostęp sieciowy w zaufanych lokalizacjach użytkownika, na przykład w domu i w pracy. |
Istnieją inne możliwości, które mogą być konieczne dla aplikacji w pewnych okolicznościach.
| Capability | Opis |
|---|---|
| enterpriseAuthentication | Umożliwia aplikacji łączenie się z zasobami sieciowymi, które wymagają poświadczeń domeny. Na przykład aplikacja, która pobiera dane z serwerów SharePoint w prywatnym intranecie. Dzięki tej możliwości poświadczenia mogą służyć do uzyskiwania dostępu do zasobów sieciowych w sieci wymagającej poświadczeń. Aplikacja z tą funkcją może personifikować Cię w sieci. Nie potrzebujesz tej możliwości, aby umożliwić aplikacji dostęp do Internetu za pośrednictwem uwierzytelnionego serwera proxy. Aby uzyskać więcej informacji, zobacz dokumentację scenariusza możliwości przedsiębiorstwa w obszarze Możliwości z ograniczeniami. |
| Bliskość | Wymagane do komunikacji zbliżeniowej bliskiego zasięgu z urządzeniami znajdującymi się w pobliżu komputera. Komunikacja bliskiego zasięgu może służyć do przesyłania danych lub łączenia się z aplikacją na pobliskim urządzeniu. Ta funkcja umożliwia aplikacji dostęp do sieci w celu nawiązania połączenia z urządzeniem w bliskiej odległości, przy użyciu zgody użytkownika na wysłanie zaproszenia lub zaakceptowanie zaproszenia. |
| sharedUserCertificates | Ta funkcja umożliwia aplikacji dostęp do certyfikatów oprogramowania i sprzętu, takich jak certyfikaty kart inteligentnych. Gdy ta funkcja jest wywoływana w czasie wykonywania, użytkownik musi podjąć działania, takie jak wstawienie karty lub wybranie certyfikatu. Dzięki tej funkcji certyfikaty oprogramowania i sprzętu lub karty inteligentnej są używane do identyfikacji w aplikacji. Ta możliwość może być używana przez pracodawcę, bank lub usługi rządowe do identyfikacji. |
Komunikacja, gdy aplikacja nie znajduje się na pierwszym planie
Zadania w tle zawierają ogólne informacje o wykonywaniu pracy, gdy aplikacja nie znajduje się na pierwszym planie. Mówiąc dokładniej, w kodzie trzeba zastosować specjalne mechanizmy, aby otrzymywać powiadomienia, gdy aplikacja nie jest aktualnie aplikacją działającą na pierwszym planie, a przez sieć nadejdą do niej dane. Wyzwalacze kanału sterowania są obsługiwane w Windows w tym celu. Aby uzyskać szczegółowe informacje, zobacz ControlChannelTrigger. Nowsza technologia zapewnia lepszą funkcjonalność przy mniejszym narzucie w niektórych scenariuszach, takich jak gniazda strumieniowe z obsługą wypychania: broker gniazd i wyzwalacze aktywności gniazd.
Jeśli aplikacja używa DatagramSocket, StreamSocket lub StreamSocketListener, może przenieść własność otwartego gniazda do brokera gniazd udostępnianego przez system, a następnie zejść z pierwszego planu, a nawet zakończyć działanie. Po nawiązaniu połączenia z przeniesionym gniazdem lub nadejściu ruchu do tego gniazda aplikacja lub wyznaczone zadanie w tle zostaną aktywowane. Jeśli aplikacja nie jest uruchomiona, zostanie uruchomiona. Broker gniazd następnie powiadamia aplikację za pomocą wyzwalacza SocketActivityTrigger, że pojawił się nowy ruch sieciowy. Twoja aplikacja przejmuje gniazdo z powrotem od brokera gniazd i obsługuje ruch w tym gnieździe. Oznacza to, że aplikacja zużywa znacznie mniej zasobów systemowych, gdy nie przetwarza aktywnie ruchu sieciowego.
Broker gniazd ma zastępować wyzwalacze kanału sterującego tam, gdzie ma to zastosowanie, ponieważ zapewnia tę samą funkcjonalność, ale przy mniejszej liczbie ograniczeń i mniejszym zużyciu pamięci. Broker gniazd może być używany przez aplikacje, które nie są aplikacjami ekranu blokady, i działa tak samo na telefonach jak na innych urządzeniach. Aplikacje nie muszą być uruchomione w chwili nadejścia ruchu, aby mogły zostać aktywowane przez brokera gniazd. Ponadto broker gniazdowy obsługuje nasłuchiwanie na gniazdach TCP, czego nie obsługują funkcje Control Channel Triggers.
Wybieranie wyzwalacza sieciowego
Istnieją pewne scenariusze, w których dowolny rodzaj wyzwalacza będzie odpowiedni. Podczas wybierania rodzaju wyzwalacza do użycia w aplikacji należy wziąć pod uwagę następujące porady.
- Jeśli używasz programu IXMLHTTPRequest2, System.Net.Http.HttpClient lub System.Net.HttpClientHandler, musisz użyć kontrolki ControlChannelTrigger.
- Jeśli używasz StreamSockets z obsługą powiadomień push, możesz użyć wyzwalaczy kanału kontrolnego, ale należy preferować SocketActivityTrigger. Ten ostatni wybór pozwala systemowi zwolnić pamięć i zmniejszyć wymagania dotyczące zasilania, gdy połączenie nie jest aktywnie używane.
- Jeśli chcesz zminimalizować ilość pamięci aplikacji, gdy nie obsługuje aktywnie żądań sieciowych, preferuj element SocketActivityTrigger , jeśli jest to możliwe.
- Jeśli chcesz, aby aplikacja mogła odbierać dane, gdy system jest w trybie wstrzymania połączonego, użyj polecenia SocketActivityTrigger.
Aby uzyskać szczegółowe informacje i przykłady korzystania z brokera gniazd, zobacz Komunikacja sieciowa w tle.
Zabezpieczone połączenia
Secure Sockets Layer (SSL) i nowsze protokoły Tls (Transport Layer Security) to protokoły kryptograficzne przeznaczone do zapewnienia uwierzytelniania i szyfrowania dla komunikacji sieciowej. Te protokoły mają na celu zapobieganie podsłuchiwaniu i manipulowaniu podczas wysyłania i odbierania danych sieciowych. Te protokoły używają modelu klient-serwer do wymiany protokołów. Te protokoły używają również certyfikatów cyfrowych i urzędów certyfikacji, aby sprawdzić, czy serwer jest tym, kim jest.
Tworzenie połączeń z bezpiecznym gniazdem
Obiekt StreamSocket można skonfigurować do używania protokołu SSL/TLS do komunikacji między klientem a serwerem. Ta obsługa protokołu SSL/TLS jest ograniczona do używania obiektu StreamSocket jako klienta w negocjacjach PROTOKOŁU SSL/TLS. Nie można używać protokołu SSL/TLS z protokołem StreamSocket utworzonym przez element StreamSocketListener po odebraniu komunikacji przychodzącej, ponieważ negocjowanie protokołu SSL/TLS jako serwera nie jest implementowane przez klasę StreamSocket .
Istnieją dwa sposoby zabezpieczania połączenia StreamSocket z protokołem SSL/TLS:
- ConnectAsync — utwórz początkowe połączenie z usługą sieciową i natychmiast negocjuj, aby używać protokołu SSL/TLS dla całej komunikacji.
- UpgradeToSslAsync — początkowo połącz się z usługą sieciową bez szyfrowania. Aplikacja może wysyłać lub odbierać dane. Następnie zaktualizuj połączenie tak, aby używało protokołu SSL/TLS do całej dalszej komunikacji.
SocketProtectionLevel określa żądany poziom ochrony gniazda, za pomocą którego aplikacja chce ustanowić lub uaktualnić połączenie. Jednak ostateczna ochrona nawiązanego połączenia jest określana w procesie negocjacji między obydwoma punktami końcowymi połączenia. Wynik może być niższy niż określony poziom ochrony, jeśli drugi punkt końcowy żąda niższego poziomu.
Po pomyślnym zakończeniu operacji asynchronicznych można pobrać żądany poziom ochrony używany w wywołaniu ConnectAsync lub UpgradeToSslAsync za pośrednictwem właściwości StreamSocketInformation.ProtectionLevel . Nie odzwierciedla to jednak rzeczywistego poziomu ochrony używanego przez połączenie.
Note
Kod nie powinien być niejawnie zależny od używania określonego poziomu ochrony lub od założenia, że dany poziom zabezpieczeń jest używany domyślnie. Poziom zabezpieczeń stale się zmienia, a protokoły i domyślne poziomy ochrony zmieniają się wraz z upływem czasu, aby uniknąć używania protokołów ze znanymi słabościami. Wartości domyślne mogą się różnić w zależności od konfiguracji poszczególnych maszyn lub od zainstalowanego oprogramowania i zastosowanych poprawek. Jeśli aplikacja zależy od użycia określonego poziomu zabezpieczeń, musisz jawnie określić ten poziom, a następnie sprawdzić, czy rzeczywiście jest używana na nawiązanym połączeniu.
Korzystanie z narzędzia ConnectAsync
Narzędzie ConnectAsync może służyć do nawiązania początkowego połączenia z usługą sieciową, a następnie natychmiast negocjować użycie protokołu SSL/TLS dla całej komunikacji. Istnieją dwie metody ConnectAsync , które obsługują przekazywanie parametru protectionLevel :
- ConnectAsync(EndpointPair, SocketProtectionLevel) — uruchamia operację asynchroniczną w obiekcie StreamSocket w celu nawiązania połączenia z lokalizacją docelową sieci zdalnej określonej jako obiekt EndpointPair i socketProtectionLevel.
- ConnectAsync(HostName, String, SocketProtectionLevel) — uruchamia operację asynchroniczną w obiekcie StreamSocket w celu nawiązania połączenia ze zdalnym miejscem docelowym określonym przez zdalną nazwę hosta, nazwę usługi zdalnej i wartość SocketProtectionLevel.
Jeśli parametr protectionLevel jest ustawiony na Windows. Networking.Sockets.SocketProtectionLevel.Ssl podczas wywoływania jednej z powyższych metod ConnectAsync usługa StreamSocket zostanie ustanowiona w celu używania protokołu SSL/TLS do szyfrowania. Ta wartość wymaga szyfrowania i nigdy nie zezwala na użycie szyfru o wartości NULL.
Normalna sekwencja do użycia z jedną z tych metod ConnectAsync jest taka sama.
- Utwórz element StreamSocket.
- Jeśli potrzebna jest zaawansowana opcja dla gniazda, użyj właściwości StreamSocket.Control, aby uzyskać wystąpienie StreamSocketControl skojarzone z obiektem StreamSocket. Ustaw właściwość w obiekcie StreamSocketControl.
- Wywołaj jedną z powyższych metod ConnectAsync , aby rozpocząć operację nawiązywania połączenia ze zdalnym miejscem docelowym i natychmiast negocjować użycie protokołu SSL/TLS.
- Siła protokołu SSL faktycznie wynegocjowana przy użyciu narzędzia ConnectAsync może być określana przez pobranie właściwości StreamSocketInformation.ProtectionLevel po pomyślnym zakończeniu operacji asynchronicznych.
Poniższy przykład tworzy protokół StreamSocket i próbuje nawiązać połączenie z usługą sieciową i natychmiast negocjować użycie protokołu SSL/TLS. Jeśli negocjacje zakończyły się pomyślnie, cała komunikacja sieciowa przy użyciu protokołu StreamSocket między klientem serwera sieciowego zostanie zaszyfrowana.
using Windows.Networking;
using Windows.Networking.Sockets;
// Define some variables and set values
StreamSocket clientSocket = new StreamSocket();
HostName serverHost = new HostName("www.contoso.com");
string serverServiceName = "https";
// For simplicity, the sample omits implementation of the
// NotifyUser method used to display status and error messages
// Try to connect to contoso using HTTPS (port 443)
try {
// Call ConnectAsync method with SSL
await clientSocket.ConnectAsync(serverHost, serverServiceName, SocketProtectionLevel.Ssl);
NotifyUser("Connected");
}
catch (Exception exception) {
// If this is an unknown status it means that the error is fatal and retry will likely fail.
if (SocketError.GetStatus(exception.HResult) == SocketErrorStatus.Unknown) {
throw;
}
NotifyUser("Connect failed with error: " + exception.Message);
// Could retry the connection, but for this simple example
// just close the socket.
clientSocket.Dispose();
clientSocket = null;
}
// Add code to send and receive data using the clientSocket
// and then close the clientSocket
#include <winrt/Windows.Networking.Sockets.h>
using namespace winrt;
...
// Define some variables, and set values.
Windows::Networking::Sockets::StreamSocket clientSocket;
Windows::Networking::HostName serverHost{ L"www.contoso.com" };
winrt::hstring serverServiceName{ L"https" };
// For simplicity, the sample omits implementation of the
// NotifyUser method used to display status and error messages.
// Try to connect to the server using HTTPS and SSL (port 443).
try
{
co_await clientSocket.ConnectAsync(serverHost, serverServiceName, Windows::Networking::Sockets::SocketProtectionLevel::Tls12);
NotifyUser(L"Connected");
}
catch (winrt::hresult_error const& exception)
{
NotifyUser(L"Connect failed with error: " + exception.message());
clientSocket = nullptr;
}
// Add code to send and receive data using the clientSocket,
// then set the clientSocket to nullptr when done to close it.
using Windows::Networking;
using Windows::Networking::Sockets;
// Define some variables and set values
StreamSocket^ clientSocket = ref new StreamSocket();
HostName^ serverHost = ref new HostName("www.contoso.com");
String^ serverServiceName = "https";
// For simplicity, the sample omits implementation of the
// NotifyUser method used to display status and error messages
// Try to connect to the server using HTTPS and SSL (port 443)
task<void>(clientSocket->ConnectAsync(serverHost, serverServiceName, SocketProtectionLevel::Ssl)).then([this] (task<void> previousTask) {
try
{
// Try getting all exceptions from the continuation chain above this point.
previousTask.Get();
NotifyUser("Connected");
}
catch (Exception^ exception)
{
NotifyUser("Connect failed with error: " + exception->Message);
clientSocket->Close();
clientSocket = null;
}
});
// Add code to send and receive data using the clientSocket
// Then close the clientSocket when done
Użyj metody UpgradeToSslAsync
Gdy kod używa polecenia UpgradeToSslAsync, najpierw ustanawia połączenie z usługą sieciową bez szyfrowania. Aplikacja może wysyłać lub odbierać dane, a następnie uaktualniać połączenie, aby korzystać z protokołu SSL/TLS, aby uzyskać dalszą komunikację.
Metoda UpgradeToSslAsync przyjmuje dwa parametry. Parametr protectionLevel wskazuje żądany poziom ochrony. Parametr validationHostName to nazwa hosta lokalizacji docelowej sieci zdalnej, która jest używana do walidacji podczas uaktualniania do protokołu SSL. Zwykle validationHostName będzie taką samą nazwą hosta, której aplikacja użyła do początkowego nawiązania połączenia. Jeśli parametr protectionLevel jest ustawiony na Windows. System.Socket.SocketProtectionLevel.Ssl podczas wywoływania polecenia UpgradeToSslAsync usługa StreamSocket musi używać protokołu SSL/TLS do szyfrowania w celu dalszej komunikacji przez gniazdo. Ta wartość wymaga szyfrowania i nigdy nie zezwala na użycie szyfru o wartości NULL.
Normalna sekwencja używana z metodą UpgradeToSslAsync jest następująca:
- Utwórz element StreamSocket.
- Jeśli potrzebna jest zaawansowana opcja dla gniazda, użyj właściwości StreamSocket.Control, aby uzyskać wystąpienie StreamSocketControl skojarzone z obiektem StreamSocket. Ustaw właściwość w obiekcie StreamSocketControl.
- Jeśli jakiekolwiek dane muszą zostać wysłane i odebrane niezaszyfrowane, wyślij je teraz.
- Wywołaj metodę UpgradeToSslAsync , aby rozpocząć operację uaktualniania połączenia w celu użycia protokołu SSL/TLS.
- Siłę protokołu SSL faktycznie wynegocjowaną przy użyciu metody UpgradeToSslAsync można określić, uzyskując właściwość StreamSocketInformation.ProtectionLevel po pomyślnym zakończeniu operacji asynchronicznych.
Poniższy przykład tworzy obiekt StreamSocket, próbuje nawiązać połączenie z usługą sieciową, wysyła pewne dane początkowe, a następnie negocjuje użycie protokołu SSL/TLS. Jeśli negocjowanie zakończy się pomyślnie, cała komunikacja sieciowa przy użyciu protokołu StreamSocket między klientem a serwerem sieciowym zostanie zaszyfrowana.
using Windows.Networking;
using Windows.Networking.Sockets;
using Windows.Storage.Streams;
// Define some variables and set values
StreamSocket clientSocket = new StreamSocket();
HostName serverHost = new HostName("www.contoso.com");
string serverServiceName = "http";
// For simplicity, the sample omits implementation of the
// NotifyUser method used to display status and error messages
// Try to connect to contoso using HTTP (port 80)
try {
// Call ConnectAsync method with a plain socket
await clientSocket.ConnectAsync(serverHost, serverServiceName, SocketProtectionLevel.PlainSocket);
NotifyUser("Connected");
}
catch (Exception exception) {
// If this is an unknown status it means that the error is fatal and retry will likely fail.
if (SocketError.GetStatus(exception.HResult) == SocketErrorStatus.Unknown) {
throw;
}
NotifyUser("Connect failed with error: " + exception.Message, NotifyType.ErrorMessage);
// Could retry the connection, but for this simple example
// just close the socket.
clientSocket.Dispose();
clientSocket = null;
return;
}
// Now try to send some data
DataWriter writer = new DataWriter(clientSocket.OutputStream);
string hello = "Hello, World! ☺ ";
Int32 len = (int) writer.MeasureString(hello); // Gets the UTF-8 string length.
writer.WriteInt32(len);
writer.WriteString(hello);
NotifyUser("Client: sending hello");
try {
// Call StoreAsync method to store the hello message
await writer.StoreAsync();
NotifyUser("Client: sent data");
writer.DetachStream(); // Detach stream, if not, DataWriter destructor will close it.
}
catch (Exception exception) {
NotifyUser("Store failed with error: " + exception.Message);
// Could retry the store, but for this simple example
// just close the socket.
clientSocket.Dispose();
clientSocket = null;
return;
}
// Now upgrade the client to use SSL
try {
// Try to upgrade to SSL
await clientSocket.UpgradeToSslAsync(SocketProtectionLevel.Ssl, serverHost);
NotifyUser("Client: upgrade to SSL completed");
// Add code to send and receive data
// The close clientSocket when done
}
catch (Exception exception) {
// If this is an unknown status it means that the error is fatal and retry will likely fail.
if (SocketError.GetStatus(exception.HResult) == SocketErrorStatus.Unknown) {
throw;
}
NotifyUser("Upgrade to SSL failed with error: " + exception.Message);
clientSocket.Dispose();
clientSocket = null;
return;
}
#include <winrt/Windows.Networking.Sockets.h>
#include <winrt/Windows.Storage.Streams.h>
using namespace winrt;
using namespace Windows::Storage::Streams;
...
// Define some variables, and set values.
Windows::Networking::Sockets::StreamSocket clientSocket;
Windows::Networking::HostName serverHost{ L"www.contoso.com" };
winrt::hstring serverServiceName{ L"https" };
// For simplicity, the sample omits implementation of the
// NotifyUser method used to display status and error messages.
// Try to connect to the server using HTTP (port 80).
try
{
co_await clientSocket.ConnectAsync(serverHost, serverServiceName, Windows::Networking::Sockets::SocketProtectionLevel::PlainSocket);
NotifyUser(L"Connected");
}
catch (winrt::hresult_error const& exception)
{
NotifyUser(L"Connect failed with error: " + exception.message());
clientSocket = nullptr;
}
// Now, try to send some data.
DataWriter writer{ clientSocket.OutputStream() };
winrt::hstring hello{ L"Hello, World! ☺ " };
uint32_t len{ writer.MeasureString(hello) }; // Gets the size of the string, in bytes.
writer.WriteInt32(len);
writer.WriteString(hello);
NotifyUser(L"Client: sending hello");
try
{
co_await writer.StoreAsync();
NotifyUser(L"Client: sent hello");
writer.DetachStream(); // Detach the stream when you want to continue using it; otherwise, the DataWriter destructor closes it.
}
catch (winrt::hresult_error const& exception)
{
NotifyUser(L"Store failed with error: " + exception.message());
// We could retry the store operation. But, for this simple example, just close the socket by setting it to nullptr.
clientSocket = nullptr;
co_return;
}
// Now, upgrade the client to use SSL.
try
{
co_await clientSocket.UpgradeToSslAsync(Windows::Networking::Sockets::SocketProtectionLevel::Tls12, serverHost);
NotifyUser(L"Client: upgrade to SSL completed");
// Add code to send and receive data using the clientSocket,
// then set the clientSocket to nullptr when done to close it.
}
catch (winrt::hresult_error const& exception)
{
// If this is an unknown status, then the error is fatal and retry will likely fail.
Windows::Networking::Sockets::SocketErrorStatus socketErrorStatus{ Windows::Networking::Sockets::SocketError::GetStatus(exception.to_abi()) };
if (socketErrorStatus == Windows::Networking::Sockets::SocketErrorStatus::Unknown)
{
throw;
}
NotifyUser(L"Upgrade to SSL failed with error: " + exception.message());
// We could retry the store operation. But for this simple example, just close the socket by setting it to nullptr.
clientSocket = nullptr;
co_return;
}
using Windows::Networking;
using Windows::Networking::Sockets;
using Windows::Storage::Streams;
// Define some variables and set values
StreamSocket^ clientSocket = ref new StreamSocket();
HostName^ serverHost = ref new HostName("www.contoso.com");
String^ serverServiceName = "http";
// For simplicity, the sample omits implementation of the
// NotifyUser method used to display status and error messages
// Try to connect to contoso using HTTP (port 80)
task<void>(clientSocket->ConnectAsync(serverHost, serverServiceName, SocketProtectionLevel::PlainSocket)).then([this] (task<void> previousTask) {
try
{
// Try getting all exceptions from the continuation chain above this point.
previousTask.Get();
NotifyUser("Connected");
}
catch (Exception^ exception)
{
NotifyUser("Connect failed with error: " + exception->Message);
clientSocket->Close();
clientSocket = null;
}
});
// Now try to send some data
DataWriter^ writer = ref new DataWriter(clientSocket->OutputStream);
String^ hello = "Hello, World! ☺ ";
Int32 len = (int) writer->MeasureString(hello); // Gets the UTF-8 string length.
writer->WriteInt32(len);
writer->WriteString(hello);
NotifyUser("Client: sending hello");
task<void>(writer->StoreAsync()).then([this] (task<void> previousTask) {
try {
// Try getting all exceptions from the continuation chain above this point.
previousTask.Get();
NotifyUser("Client: sent hello");
writer->DetachStream(); // Detach stream, if not, DataWriter destructor will close it.
}
catch (Exception^ exception) {
NotifyUser("Store failed with error: " + exception->Message);
// Could retry the store, but for this simple example
// just close the socket.
clientSocket->Close();
clientSocket = null;
return;
}
});
// Now upgrade the client to use SSL
task<void>(clientSocket->UpgradeToSslAsync(SocketProtectionLevel::Ssl, serverHost)).then([this] (task<void> previousTask) {
try {
// Try getting all exceptions from the continuation chain above this point.
previousTask.Get();
NotifyUser("Client: upgrade to SSL completed");
// Add code to send and receive data
// Then close clientSocket when done
}
catch (Exception^ exception) {
// If this is an unknown status it means that the error is fatal and retry will likely fail.
if (SocketError.GetStatus(exception.HResult) == SocketErrorStatus.Unknown) {
throw;
}
NotifyUser("Upgrade to SSL failed with error: " + exception.Message);
clientSocket->Close();
clientSocket = null;
return;
}
});
Tworzenie bezpiecznych połączeń protokołu WebSocket
Podobnie jak w przypadku tradycyjnych połączeń gniazd, połączenia protokołu WebSocket można również szyfrować przy użyciu protokołu Transport Layer Security (TLS)/Secure Sockets Layer (SSL) podczas korzystania z funkcji StreamWebSocket i MessageWebSocket dla aplikacji Windows. W większości przypadków należy użyć bezpiecznego połączenia protokołu WebSocket. Zwiększy to prawdopodobieństwo pomyślnego nawiązania połączenia, ponieważ wiele serwerów proxy odrzuci niezaszyfrowane połączenia protokołu WebSocket.
Przykłady tworzenia lub uaktualniania bezpiecznego połączenia gniazda z usługą sieciową można znaleźć w temacie Jak zabezpieczyć połączenia protokołu WebSocket za pomocą protokołu TLS/SSL.
Oprócz szyfrowania TLS/SSL, serwer może wymagać wartości nagłówka Sec-WebSocket-Protocol do zakończenia początkowego uzgadniania połączenia. Ta wartość reprezentowana przez właściwości StreamWebSocketInformation.Protocol i MessageWebSocketInformation.Protocol wskazuje wersję protokołu połączenia i umożliwia serwerowi poprawne interpretowanie uzgadniania otwierania i wymiany danych. Korzystając z tych informacji o protokole, jeśli w dowolnym momencie serwer nie może interpretować danych przychodzących w bezpieczny sposób, można zamknąć połączenie.
Jeśli początkowe żądanie klienta nie zawiera tej wartości albo zawiera wartość, która nie odpowiada wartości oczekiwanej przez serwer, to w przypadku błędu podczas uzgadniania połączenia WebSocket serwer przesyła klientowi oczekiwaną wartość.
Authentication
Jak podać poświadczenia uwierzytelniania podczas nawiązywania połączenia za pośrednictwem sieci.
Dostarczanie certyfikatu klienta z klasą StreamSocket
Windows. Networking.Sockets.StreamSocket, klasa obsługuje używanie protokołu SSL/TLS do uwierzytelniania serwera, z którym rozmawia aplikacja. W niektórych przypadkach aplikacja musi również uwierzytelniać się na serwerze przy użyciu certyfikatu klienta TLS. W Windows 10 można podać certyfikat klienta w obiekcie StreamSocket.Control (należy to ustawić przed uruchomieniem uzgadniania protokołu TLS). Jeśli serwer zażąda certyfikatu klienta, Windows odpowie przy użyciu podanego certyfikatu.
Oto fragment kodu pokazujący sposób implementacji tego kodu:
var socket = new StreamSocket();
Windows.Security.Cryptography.Certificates.Certificate certificate = await GetClientCert();
socket.Control.ClientCertificate = certificate;
await socket.ConnectAsync(destination, SocketProtectionLevel.Tls12);
Podawanie poświadczeń uwierzytelniania w usłudze internetowej
Interfejsy API sieci umożliwiające aplikacjom interakcję z bezpiecznymi usługami internetowymi zapewniają własne metody inicjowania klienta lub ustawiania nagłówka żądania przy użyciu poświadczeń uwierzytelniania serwera i serwera proxy. Każda metoda jest ustawiana przy użyciu obiektu PasswordCredential , który wskazuje nazwę użytkownika, hasło i zasób, dla którego są używane te poświadczenia. Poniższa tabela zawiera mapowanie tych interfejsów API:
Obsługa wyjątków sieciowych
W większości obszarów programowania wyjątek wskazuje znaczący problem lub awarię spowodowaną przez pewną wadę w programie. W programowaniu sieci istnieje dodatkowe źródło wyjątków: sama sieć i charakter komunikacji sieciowej. Komunikacja sieciowa jest z natury zawodna i podatna na nieoczekiwane awarie. Dla każdego ze sposobów korzystania z sieci przez aplikację należy zachować pewne informacje o stanie; kod aplikacji musi obsługiwać wyjątki sieciowe, aktualizując te informacje o stanie i inicjując odpowiednią logikę, aby aplikacja ponownie ustanowić lub ponowić próbę niepowodzenia komunikacji.
Gdy aplikacje universal Windows zgłaszają wyjątek, program obsługi wyjątków może pobrać bardziej szczegółowe informacje na temat przyczyny wyjątku, aby lepiej zrozumieć błąd i podejmować odpowiednie decyzje.
Każda projekcja języka obsługuje metodę uzyskiwania dostępu do tych bardziej szczegółowych informacji. Wyjątek jest reprezentowany jako wartość HRESULT w aplikacjach Uniwersalnej Platformy systemu Windows. Plik dołączania Winerror.h zawiera bardzo dużą listę możliwych wartości HRESULT , które zawierają błędy sieciowe.
Interfejsy API sieci obsługują różne metody pobierania tych szczegółowych informacji na temat przyczyny wyjątku.
- Niektóre interfejsy API udostępniają metodę pomocnika, która konwertuje wartość HRESULT z wyjątku na wartość wyliczenia.
- Inne interfejsy API udostępniają metodę pobierania rzeczywistej wartości HRESULT .