Uwaga
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.
Możliwości
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.
Zdolność | Opis |
---|---|
InternetKlient | 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 dostęp do sieci przychodzących i wychodzących z Internetu oraz z sieci w miejscach publicznych, takich jak lotniska i kawiarnie. |
klient-serwer sieci prywatnej | Aplikacja uzyskuje dostęp do połączeń sieciowych przychodzących i wychodzących w zaufanych miejscach użytkownika, takich jak dom i praca. |
Istnieją inne możliwości, które mogą być konieczne dla aplikacji w pewnych okolicznościach.
Zdolność | 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 programu 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 funkcjonalności |
sąsiedztwa | Wymagana do komunikacji zbliżeniowej z urządzeniami w pobliżu komputera. Komunikacja bliskiego zasięgu może być używana do wysyłania lub nawiązywania połączenia 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. |
wspólneCertyfikatyUżytkownika | 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 możliwości 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
Obsługa aplikacji z zadaniami w tle zawiera ogólne informacje o korzystaniu z zadań w tle do wykonania, gdy aplikacja nie znajduje się na pierwszym planie. W szczególności kod musi wykonać specjalne kroki, aby otrzymywać powiadomienia, gdy nie jest to bieżąca aplikacja pierwszego planu i dane docierają do niej przez sieć. W tym celu użyto wyzwalaczy kanału sterowania w systemie Windows 8 i są one nadal obsługiwane w systemie Windows 10. Pełne informacje na temat korzystania z wyzwalaczy kanału sterowania można znaleźć tutaj. Nowa technologia w systemie Windows 10 zapewnia lepszą funkcjonalność przy niższym obciążeniu w niektórych scenariuszach, takich jak gniazda strumieni z obsługą wypychania: broker gniazd i wyzwalacze aktywności gniazd.
Jeśli aplikacja używa DatagramSocket, StreamSocketlub StreamSocketListener, to może przenieść własność otwartego gniazda sieciowego do brokera gniazd dostarczonego przez system, a następnie opuścić pierwszy plan lub nawet się zakończyć. 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 aktywna, zostanie uruchomiona. Następnie broker gniazd powiadamia aplikację przy użyciu SocketActivityTrigger, że dotarł nowy ruch. Aplikacja odzyskuje gniazdo od brokera gniazd i przetwarza ruch na tym gnieździe. Oznacza to, że aplikacja zużywa znacznie mniej zasobów systemowych, gdy nie przetwarza aktywnie ruchu sieciowego.
Broker gniazd ma zastąpić wyzwalacze kanału sterowania, gdzie to możliwe, ponieważ zapewnia tę samą funkcjonalność, ale z mniejszą liczbą ograniczeń i mniejszym zapotrzebowaniem na pamięć. Broker gniazda może być używany przez aplikacje, które nie są aplikacjami ekranu blokady, i działa w taki sam sposób na telefonach, jak na innych urządzeniach. Aplikacje nie muszą być działające, gdy ruch dociera, aby zostać uruchomione przez brokera gniazd. Broker gniazd obsługuje nasłuchiwanie na gniazdach TCP, czego wyzwalacze kanału sterowania nie obsługują.
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ą wypychania, możesz użyć wyzwalaczy kanału sterowania, 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 podłączonym trybie gotowości, użyj 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 SSL/TLS ogranicza się do użycia obiektu StreamSocket jako klienta w negocjacjach 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 uaktualnij połączenie do używania SSL/TLS do 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 ConnectAsync lub UpgradeToSslAsync wywołania za pośrednictwem właściwości StreamSocketinformation.ProtectionLevel. Nie odzwierciedla to jednak rzeczywistego poziomu ochrony używanego przez połączenie.
Uwaga / Notatka
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, aby nawiązać połączenie ze zdalnym miejscem określonym przez zdalną nazwę hosta, nazwę usługi i SocketProtectionLevel.
Jeśli parametr protectionLevel jest ustawiony na Windows.Networking.Sockets.SocketProtectionLevel.Ssl podczas wywoływania jednej z powyższych metod ConnectAsync, należy ustanowić StreamSocket używać 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 StreamSocket.
- Jeśli wymagana jest zaawansowana opcja gniazda, użyj właściwości StreamSocket.Control, aby pobrać wystąpienie StreamSocketControl skojarzone z obiektem StreamSocket. Ustaw właściwość na 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 StreamSocket i próbuje nawiązać połączenie z usługą sieciową oraz natychmiast rozpocząć negocjacje dotyczące użycia 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 = new ref StreamSocket();
HostName^ serverHost = new ref 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 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 jest nazwą hosta docelowego miejsca w sieci zdalnej, który jest używany do walidacji podczas aktualizacji do protokołu SSL. Zwykle validationHostName będzie tą 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 za pośrednictwem gniazda. 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 StreamSocket.
- Jeśli wymagana jest zaawansowana opcja gniazda, użyj właściwości StreamSocket.Control, aby pobrać wystąpienie StreamSocketControl skojarzone z obiektem StreamSocket. Ustaw właściwość na 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łę SSL faktycznie wynegocjowaną przy użyciu UpgradeToSslAsync można określić, pobierając właściwość StreamSocketInformation.ProtectionLevel po pomyślnym zakończeniu operacji asynchronicznej.
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 = new ref StreamSocket();
Hostname^ serverHost = new ref 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 = new ref 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(clientSocket.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 WebSocket mogą być również szyfrowane przy użyciu protokołu Transport Layer Security (TLS)/Secure Sockets Layer (SSL) podczas korzystania z StreamWebSocket i MessageWebSocket funkcji dla aplikacji UWP. 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 ukończenia początkowego uzgadniania. Ta wartość, reprezentowana przez właściwości StreamWebSocketInformation.Protocol i MessageWebSocketInformation.Protocol, wskazują wersję protokołu połączenia sieciowego i umożliwiają serwerowi poprawne interpretowanie otwierającego uścisku dłoni oraz wymianę danych później. 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 od klienta nie zawiera tej wartości lub zawiera wartość, która nie jest zgodna z oczekiwaniami serwera, oczekiwana wartość jest wysyłana z serwera do klienta w przypadku błędu podczas uzgadniania protokołu WebSocket.
Uwierzytelnianie
Jak podać poświadczenia uwierzytelniania podczas nawiązywania połączenia za pośrednictwem sieci.
Dostarczanie certyfikatu klienta z klasą StreamSocket
Klasa Windows.Networking.Sockets.StreamSocket 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 systemie Windows 10 można podać certyfikat klienta w obiekcie StreamSocket.Control (należy to ustawić przed uruchomieniem uzgadniania PROTOKOŁU TLS). Jeśli serwer żąda certyfikatu klienta, system 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 uniwersalne systemu 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 przedstawiany jako HRESULT w aplikacjach uniwersalnych Windows. Plik nagłówkowy Winerror. h zawiera bardzo dużą listę możliwych wartości HRESULT, które obejmują 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.