Hinweis
Für den Zugriff auf diese Seite ist eine Autorisierung erforderlich. Sie können versuchen, sich anzumelden oder das Verzeichnis zu wechseln.
Für den Zugriff auf diese Seite ist eine Autorisierung erforderlich. Sie können versuchen, das Verzeichnis zu wechseln.
Dinge, die Sie für jede netzwerkfähige App ausführen müssen.
Fähigkeiten
Um Netzwerke verwenden zu können, müssen Sie ihrem App-Manifest geeignete Funktionselemente hinzufügen. Wenn keine Netzwerkfunktion im Manifest Ihrer App angegeben ist, verfügt Ihre App über keine Netzwerkfunktion, und jeder Versuch, eine Verbindung mit dem Netzwerk herzustellen, schlägt fehl.
Im Folgenden sind die am häufigsten verwendeten Netzwerkfunktionen aufgeführt.
Fähigkeit | BESCHREIBUNG |
---|---|
Internetclient | Bietet ausgehenden Zugriff auf das Internet und Netzwerke an öffentlichen Orten, z. B. Flughäfen und Cafés. Die meisten Apps, die Internetzugriff erfordern, sollten diese Funktion verwenden. |
internetClientServer | Ermöglicht der App eingehenden und ausgehenden Netzwerkzugriff über das Internet und Netzwerke an öffentlichen Orten wie Flughäfen und Cafés. |
Private-Netzwerk-Client-Server | Ermöglicht der App eingehenden und ausgehenden Netzwerkzugriff an den vertrauenswürdigen Orten des Benutzers, z. B. zu Hause und am Arbeitsplatz. |
Es gibt andere Funktionen, die unter bestimmten Umständen für Ihre App erforderlich sein können.
Fähigkeit | BESCHREIBUNG |
---|---|
enterpriseAuthentication | Ermöglicht einer App, eine Verbindung mit Netzwerkressourcen herzustellen, für die Domänenanmeldeinformationen erforderlich sind. Beispielsweise eine App, die Daten von SharePoint-Servern in einem privaten Intranet abruft. Mit dieser Funktion können Ihre Anmeldeinformationen für den Zugriff auf Netzwerkressourcen in einem Netzwerk verwendet werden, für das Anmeldeinformationen erforderlich sind. Eine App mit dieser Funktion kann Sie im Netzwerk imitieren. Sie benötigen diese Funktion nicht, damit Ihre App über einen Authentifizierungsproxy auf das Internet zugreifen kann. Weitere Informationen finden Sie in der Dokumentation für das Szenario der Enterprise Fähigkeit in Eingeschränkte Fähigkeiten. |
Nähe | Erforderlich für die Kommunikation im Nahbereich mit Geräten in der Nähe des Computers. Nahfeldnäherung kann verwendet werden, um eine Anwendung auf einem nahe gelegenen Gerät zu senden oder eine Verbindung mit einer Anwendung herzustellen. Mit dieser Funktion kann eine App auf das Netzwerk zugreifen, um eine Verbindung mit einem Gerät in unmittelbarer Nähe herzustellen, mit der Zustimmung des Benutzers, eine Einladung zu senden oder eine Einladung anzunehmen. |
geteilteBenutzerzertifikate | Mit dieser Funktion kann eine App auf Software- und Hardwarezertifikate wie Smartcardzertifikate zugreifen. Wenn diese Funktion zur Laufzeit aufgerufen wird, muss der Benutzer Maßnahmen ergreifen, z. B. eine Karte einfügen oder ein Zertifikat auswählen. Mit dieser Funktion werden Ihre Software- und Hardwarezertifikate oder eine Smartcard zur Identifizierung in der App verwendet. Diese Funktion kann von Ihrem Arbeitgeber, Ihrer Bank oder von Behörden zur Identifizierung verwendet werden. |
Kommunikation, wenn sich Ihre App nicht im Vordergrund befindet
Unterstützen Sie Ihre App mit Hintergrundaufgaben enthält allgemeine Informationen zur Verwendung von Hintergrundaufgaben, um Aufgaben auszuführen, wenn ihre App nicht im Vordergrund ist. Genauer gesagt muss Ihr Code spezielle Schritte ausführen, um benachrichtigt zu werden, wenn es sich nicht um die aktuelle Vordergrund-App handelt und Daten über das Netzwerk dafür eingehen. Sie haben Kontrollkanal-Trigger für diesen Zweck in Windows 8 verwendet, und sie werden weiterhin in Windows 10 unterstützt. Vollständige Informationen zur Verwendung von Steuerkanaltriggern finden Sie hier. Eine neue Technologie in Windows 10 bietet für einige Szenarien, wie beispielsweise Push-fähige Stream-Sockets, eine bessere Funktionalität bei geringerem Aufwand: den Socket-Broker und Socket-Aktivitätsauslöser.
Wenn Ihre App DatagramSocket-, StreamSocket-oder StreamSocketListener-verwendet, kann Ihre App den Besitz eines geöffneten Sockets an einen vom System bereitgestellten Socket-Broker übertragen und dann den Vordergrund verlassen oder sogar beendet werden. Wenn eine Verbindung über den übertragenen Socket hergestellt wird oder Datenverkehr auf diesem Socket eingeht, werden Ihre App oder die festgelegte Hintergrundaufgabe aktiviert. Wenn Ihre App nicht läuft, wird sie gestartet. Der Socketbroker benachrichtigt Ihre App dann mit einem SocketActivityTrigger, dass neuer Datenverkehr eingegangen ist. Ihre App beansprucht den Socket vom Socket-Broker zurück und verarbeitet den Datenverkehr auf dem Socket. Dies bedeutet, dass Ihre App viel weniger Systemressourcen verbraucht, wenn der Netzwerkdatenverkehr nicht aktiv verarbeitet wird.
Der Socketbroker soll Steuerkanaltrigger ersetzen, sofern er anwendbar ist, da er die gleiche Funktionalität bereitstellt, jedoch mit weniger Einschränkungen und einem geringeren Speicherbedarf. Der Socket-Broker kann von Apps verwendet werden, die keine Sperrbildschirm-Apps sind, und wird auf Smartphones genauso verwendet wie auf anderen Geräten. Apps müssen nicht ausgeführt werden, wenn Datenverkehr eingeht, um vom Socket-Broker aktiviert zu werden. Und der Socketbroker unterstützt das Lauschen auf TCP-Sockets, was Steuerkanaltrigger nicht unterstützen.
Auswahl eines Netzwerktriggers
Es gibt einige Szenarien, in denen beide Arten von Trigger geeignet wären. Wenn Sie auswählen, welche Art von Trigger in Ihrer App verwendet werden soll, beachten Sie die folgenden Hinweise.
- Wenn Sie IXMLHTTPRequest2, System.Net.Http.HttpClient oder System.Net.Http.HttpClientHandlerverwenden, müssen Sie ControlChannelTriggerverwenden.
- Wenn Sie pushfähige StreamSocketsverwenden, können Sie Steuerkanaltrigger verwenden, sollten jedoch SocketActivityTriggerbevorzugen. Letztere Wahl ermöglicht es dem System, Arbeitsspeicher freizugeben und die Energieanforderungen zu reduzieren, wenn die Verbindung nicht aktiv verwendet wird.
- Wenn Sie den Speicherbedarf Ihrer App minimieren möchten, wenn Ihre App gerade keine Netzwerkanforderungen bearbeitet, bevorzugen Sie SocketActivityTrigger, wann immer es möglich ist.
- Wenn Ihre App Daten empfangen soll, während das System im verbundenen Standby-Modus ist, verwenden Sie SocketActivityTrigger.
Ausführliche Informationen und Beispiele zur Verwendung des Socketbrokers finden Sie unter Netzwerkkommunikation im Hintergrund.
Gesicherte Verbindungen
Secure Sockets Layer (SSL) und die neueren Transport Layer Security (TLS) sind kryptografische Protokolle, die für die Authentifizierung und Verschlüsselung für die Netzwerkkommunikation entwickelt wurden. Diese Protokolle dienen dazu, Lauschangriffe und Manipulationen beim Senden und Empfangen von Netzwerkdaten zu verhindern. Diese Protokolle verwenden ein Clientservermodell für den Protokollaustausch. Diese Protokolle verwenden auch digitale Zertifikate und Zertifizierungsstellen, um zu überprüfen, ob der Server derjenige ist, für den er sich ausgibt.
Erstellen sicherer Socketverbindungen
Ein StreamSocket--Objekt kann so konfiguriert werden, dass SSL/TLS für die Kommunikation zwischen dem Client und dem Server verwendet wird. Diese Unterstützung für SSL/TLS ist auf die Verwendung des StreamSocket- Objekts als Client in der SSL/TLS-Aushandlung beschränkt. Sie können SSL/TLS nicht mit dem StreamSocket- verwenden, das von einem StreamSocketListener erstellt wurde, wenn eingehende Kommunikation empfangen wird, da ssl/TLS-Aushandlung als Server nicht von der StreamSocket- Klasse implementiert wird.
Es gibt zwei Möglichkeiten zum Sichern einer StreamSocket- Verbindung mit SSL/TLS:
- ConnectAsync- – Stellen Sie die erste Verbindung mit einem Netzwerkdienst her und verhandeln Sie sofort, um SSL/TLS für alle Kommunikationen zu verwenden.
- UpgradeToSslAsync – Verbinden Sie sich zunächst mit einem Netzwerkdienst ohne Verschlüsselung. Die App kann Daten senden oder empfangen. Aktualisieren Sie dann die Verbindung, um SSL/TLS für alle weiteren Kommunikationen zu verwenden.
Der SocketProtectionLevel gibt die gewünschte Socketschutzebene an, mit der die App die Verbindung herstellen oder aktualisieren möchte. Die letztendliche Schutzebene der hergestellten Verbindung wird jedoch in einem Aushandlungsprozess zwischen beiden Endpunkten der Verbindung bestimmt. Das Ergebnis kann eine niedrigere Schutzebene sein als die angegebene, wenn der andere Endpunkt eine niedrigere Ebene anfordert.
Nachdem der asynchrone Vorgang erfolgreich abgeschlossen wurde, können Sie über die StreamSocketinformation.ProtectionLevel--Eigenschaft die angeforderte Schutzebene abrufen, die im ConnectAsync-- oder UpgradeToSslAsync--Aufruf verwendet wurde. Dies spiegelt jedoch nicht die tatsächliche Schutzebene wider, die die Verbindung verwendet.
Hinweis
Ihr Code sollte nicht implizit von der Verwendung einer bestimmten Schutzebene oder von der Annahme abhängen, dass eine bestimmte Sicherheitsstufe standardmäßig verwendet wird. Die Sicherheitslandschaft ändert sich ständig, und Protokolle und Standardschutzstufen ändern sich im Laufe der Zeit, um die Verwendung von Protokollen mit bekannten Schwachstellen zu vermeiden. Die Standardwerte können je nach Konfiguration einzelner Computer variieren oder welche Software installiert ist und welche Patches angewendet wurden. Wenn Ihre App von der Verwendung einer bestimmten Sicherheitsstufe abhängt, müssen Sie diese Ebene explizit angeben und dann überprüfen, ob sie tatsächlich für die hergestellte Verbindung verwendet wird.
Verwenden von ConnectAsync
ConnectAsync- kann verwendet werden, um die erste Verbindung mit einem Netzwerkdienst herzustellen und dann sofort die Verwendung von SSL/TLS für alle Kommunikationen auszuhandeln. Es gibt zwei ConnectAsync- Methoden, die das Übergeben eines protectionLevel-Parameters unterstützen:
- ConnectAsync(EndpointPair, SocketProtectionLevel) – Startet einen asynchronen Vorgang für ein StreamSocket--Objekt, um eine Verbindung mit einem entfernten Netzwerkziel herzustellen, das als ein EndpointPair--Objekt und einem SocketProtectionLevel-angegeben ist.
- ConnectAsync(HostName, String, SocketProtectionLevel) – Startet einen asynchronen Vorgang für ein StreamSocket--Objekt, um eine Verbindung mit einem Remoteziel herzustellen, das durch einen Remotehostnamen, einen Remotedienstnamen und einen SocketProtectionLevel-angegeben wird.
Wenn der Parameter protectionLevel auf Windows.Networking.Sockets.SocketProtectionLevel.Ssl festgelegt ist, wenn eine der oben genannten ConnectAsync Methoden aufgerufen wird, muss das StreamSocket eingerichtet werden, um SSL/TLS zur Verschlüsselung zu verwenden. Dieser Wert erfordert Verschlüsselung und lässt niemals eine NULL-Verschlüsselung zu.
Die normale Sequenz, die mit einer der ConnectAsync- Methoden verwendet wird, ist identisch.
- Erstellen Sie eine StreamSocket.
- Wenn eine erweiterte Option für den Socket erforderlich ist, verwenden Sie die StreamSocket.Control Eigenschaft, um die StreamSocketControl Instanz zu erhalten, die einem StreamSocket-Objekt zugeordnet ist. Legen Sie eine Eigenschaft am StreamSocketControl fest.
- Rufen Sie eine der oben genannten ConnectAsync- Methoden auf, um einen Vorgang zum Herstellen einer Verbindung mit einem entfernten Ziel zu starten und die Verwendung von SSL/TLS sofort auszuhandeln.
- Die tatsächlich mit ConnectAsync- ausgehandelte SSL-Stärke kann bestimmt werden, indem die StreamSocketInformation.ProtectionLevel---Eigenschaft abgerufen wird, nachdem der asynchrone Vorgang erfolgreich abgeschlossen wurde.
Im folgenden Beispiel wird ein StreamSocket- erstellt und versucht, eine Verbindung mit dem Netzwerkdienst herzustellen und sofort die Verwendung von SSL/TLS auszuhandeln. Wenn die Verhandlung erfolgreich ist, wird die gesamte Netzwerkkommunikation zwischen dem Client und dem Netzwerkserver, die den StreamSocket nutzt, verschlüsselt.
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
Verwenden von UpgradeToSslAsync
Wenn Ihr Code UpgradeToSslAsyncverwendet, stellt er zunächst eine Verbindung zu einem Netzwerkdienst ohne Verschlüsselung her. Die App sendet oder empfängt möglicherweise einige Daten und aktualisiert dann die Verbindung, um SSL/TLS für alle weiteren Kommunikationen zu verwenden.
Die UpgradeToSslAsync--Methode verwendet zwei Parameter. Der parameter protectionLevel gibt die gewünschte Schutzebene an. Der validationHostName Parameter ist der Hostname des Zielhosts im Remotenetzwerk, der bei der Aktualisierung auf SSL zur SSL-Validierung verwendet wird. Normalerweise wäre der validationHostName derselbe Hostname, den die App ursprünglich verwendet hat, um die Verbindung herzustellen. Wenn der parameter protectionLevel auf Windows.System.Socket.SocketProtectionLevel.Ssl festgelegt ist, wenn UpgradeToSslAsync-aufgerufen wird, muss die StreamSocket- ssl/TLS für die Verschlüsselung für die weitere Kommunikation über den Socket verwenden. Dieser Wert erfordert Verschlüsselung und lässt niemals eine NULL-Verschlüsselung zu.
Die normale Sequenz, die mit der UpgradeToSslAsync Methode verwendet werden soll, lautet wie folgt:
- Erstellen Sie eine StreamSocket.
- Wenn eine erweiterte Option für den Socket erforderlich ist, verwenden Sie die StreamSocket.Control Eigenschaft, um die StreamSocketControl Instanz zu erhalten, die einem StreamSocket-Objekt zugeordnet ist. Legen Sie eine Eigenschaft am StreamSocketControl fest.
- Wenn Daten unverschlüsselt gesendet und empfangen werden müssen, senden Sie sie jetzt.
- Rufen Sie die UpgradeToSslAsync--Methode auf, um einen Vorgang zu starten, um die Verbindung auf die Verwendung von SSL/TLS zu aktualisieren.
- Die tatsächlich mit UpgradeToSslAsync ausgehandelte SSL-Stärke kann bestimmt werden, indem die StreamSocketinformation.ProtectionLevel-Eigenschaft abgerufen wird, nachdem der asynchrone Vorgang erfolgreich abgeschlossen wurde.
Im folgenden Beispiel wird ein StreamSocket-erstellt, versucht, eine Verbindung mit dem Netzwerkdienst herzustellen, einige anfängliche Daten zu senden und dann ssl/TLS zu verwenden. Wenn die Aushandlung erfolgreich ist, wird die gesamte Netzwerkkommunikation unter Verwendung des StreamSocket zwischen dem Client und dem Netzwerkserver verschlüsselt.
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;
}
});
Erstellen sicherer WebSocket-Verbindungen
Wie herkömmliche Socketverbindungen können WebSocket-Verbindungen auch mit TLS (Transport Layer Security)/Secure Sockets Layer (SSL) verschlüsselt werden, wenn sie die StreamWebSocket- und MessageWebSocket- Features für eine UWP-App verwenden. In den meisten Fällen sollten Sie eine sichere WebSocket-Verbindung verwenden. Dies erhöht die Wahrscheinlichkeit, dass Ihre Verbindung erfolgreich ist, da viele Proxys unverschlüsselte WebSocket-Verbindungen ablehnen.
Beispiele, wie man eine sichere Socketverbindung zu einem Netzwerkdienst erstellt oder aktualisiert, finden Sie unter Sichere WebSocket-Verbindungen mit TLS/SSL.
Zusätzlich zur TLS/SSL-Verschlüsselung erfordert ein Server möglicherweise einen Sec-WebSocket-Protocol Headerwert, um den anfänglichen Handshake abzuschließen. Dieser Wert, dargestellt durch die Eigenschaften StreamWebSocketInformation.Protocol und MessageWebSocketInformation.Protocol, gibt die Protokollversion der Verbindung an und ermöglicht dem Server, den öffnenden Handshake und die anschließend ausgetauschten Daten korrekt zu interpretieren. Wenn der Server die eingehenden Daten nicht sicher interpretieren kann, kann die Verbindung unter Verwendung dieser Protokollinformationen geschlossen werden.
Wenn die ursprüngliche Anfrage des Clients entweder diesen Wert nicht enthält oder einen Wert bereitstellt, der nicht mit dem übereinstimmt, was der Server erwartet, wird der erwartete Wert bei einem WebSocket-Handshake-Fehler vom Server an den Client gesendet.
Authentifizierung
So geben Sie Authentifizierungsdaten bei der Verbindung über das Netzwerk an.
Bereitstellen eines Clientzertifikats mit der StreamSocket-Klasse
Die Windows.Networking.Sockets.StreamSocket Klasse unterstützt die Verwendung von SSL/TLS zum Authentifizieren des Servers, mit dem die App spricht. In bestimmten Fällen muss sich die App auch mit einem TLS-Clientzertifikat auf dem Server authentifizieren. In Windows 10 können Sie ein Clientzertifikat für das StreamSocket.Control-Objekt bereitstellen (dies muss festgelegt werden, bevor der TLS-Handshake gestartet wird). Wenn der Server das Clientzertifikat anfordert, antwortet Windows mit dem bereitgestellten Zertifikat.
Nachfolgend sehen Sie einen Codeausschnitt, der zeigt, wie Sie folgendes implementieren:
var socket = new StreamSocket();
Windows.Security.Cryptography.Certificates.Certificate certificate = await GetClientCert();
socket.Control.ClientCertificate = certificate;
await socket.ConnectAsync(destination, SocketProtectionLevel.Tls12);
Bereitstellen von Authentifizierungsanmeldeinformationen für einen Webdienst
Die Netzwerk-APIs, mit denen Apps mit sicheren Webdiensten interagieren können, stellen jeweils eigene Methoden bereit, um einen Client zu initialisieren oder einen Anforderungsheader mit Server- und Proxyauthentifizierungsanmeldeinformationen festzulegen. Jede Methode wird mit einem PasswordCredential-Objekt festgelegt, das einen Benutzernamen, ein Kennwort und die Ressource angibt, für die diese Anmeldeinformationen verwendet werden. Die folgende Tabelle enthält eine Zuordnung dieser APIs:
Behandlung von Netzausnahmen
In den meisten Bereichen der Programmierung weist eine Ausnahme auf ein erhebliches Problem oder einen Fehler hin, der durch einige Fehler im Programm verursacht wird. Bei der Netzwerkprogrammierung gibt es eine zusätzliche Quelle für Ausnahmen: das Netzwerk selbst und die Art der Netzwerkkommunikation. Die Netzwerkkommunikation ist inhärent unzuverlässig und anfällig für unerwartete Fehler. Für jede Art der Netzwerknutzung Ihrer App müssen Sie einige Statusinformationen beibehalten, und Ihr App-Code muss Netzwerkausnahmen verarbeiten, indem diese Statusinformationen aktualisiert werden und geeignete Logik initiiert wird, um Kommunikationsfehler zu beheben oder einen erneuten Verbindungsversuch zu unternehmen.
Wenn universelle Windows-Apps eine Ausnahme auslösen, kann Ihr Ausnahmehandler detailliertere Informationen zur Ursache der Ausnahme abrufen, um den Fehler besser zu verstehen und geeignete Entscheidungen zu treffen.
Jede Sprachprojektion unterstützt eine Methode für den Zugriff auf diese detaillierteren Informationen. Eine Ausnahme erscheint als HRESULT--Wert in Universal Windows-Apps. Die enthaltene Datei Winerror.h enthält eine sehr große Liste möglicher HRESULT- Werte, darunter Netzwerkfehler.
Die Netzwerk-APIs unterstützen verschiedene Methoden zum Abrufen dieser detaillierten Informationen zur Ursache einer Ausnahme.
- Einige APIs stellen eine Hilfsmethode bereit, die den HRESULT--Wert aus der Ausnahme in einen Enumerationswert konvertiert.
- Andere APIs stellen eine Methode bereit, um den tatsächlichen HRESULT--Wert abzurufen.