Примечание.
Для доступа к этой странице требуется авторизация. Вы можете попробовать войти или изменить каталоги.
Для доступа к этой странице требуется авторизация. Вы можете попробовать изменить каталоги.
Действия, которые необходимо сделать для любого приложения с поддержкой сети.
Capabilities
Чтобы использовать сеть, необходимо добавить соответствующие элементы возможностей в манифест приложения. Если в манифесте приложения нет сетевых возможностей, приложение не сможет подключиться к сети, и любая попытка подключиться к сети завершится ошибкой.
Ниже приведены наиболее используемые сетевые возможности.
| Функциональность | Описание |
|---|---|
| InternetClient | Предоставляет исходящий доступ к Интернету и сетям в общественных местах, таких как аэропорты и кафе. Большинство приложений, которым требуется доступ к Интернету, должны использовать эту возможность. |
| InternetClientServer | Предоставляет приложению входящий и исходящий сетевой доступ из Интернета и сетей в общественных местах, таких как аэропорты и кафе. |
| privateNetworkClientServer | Предоставляет приложению входящий и исходящий сетевой доступ в надежных местах пользователя, например дома и работы. |
Существуют и другие возможности, которые могут потребоваться для вашего приложения в определенных обстоятельствах.
| Функциональность | Описание |
|---|---|
| enterpriseAuthentication | Позволяет приложению подключаться к сетевым ресурсам, которым требуются учетные данные домена. Например, приложение, которое извлекает данные из SharePoint серверов в частной интрасети. С помощью этой возможности учетные данные можно использовать для доступа к сетевым ресурсам в сети, требующей учетных данных. Приложение с этой возможностью может олицетворить вас в сети. Для доступа приложения к Интернету через прокси-сервер проверки подлинности не требуется. Дополнительные сведения см. в документации по сценарию возможностей Enterprise в ограниченных возможностях. |
| Близости | Требуется для связи малого радиуса действия с устройствами, находящимися рядом с компьютером. Технологию связи малого радиуса действия можно использовать для отправки данных приложению или подключения к нему на устройстве, находящемся поблизости. Эта возможность позволяет приложению получить доступ к сети для подключения к устройству в близком расположении с согласием пользователя на отправку приглашения или принятие приглашения. |
| sharedUserCertificates | Эта возможность позволяет приложению получать доступ к сертификатам программного обеспечения и оборудования, таким как сертификаты смарт-карт. Когда эта возможность вызывается во время выполнения, пользователь должен принять меры, такие как вставка карточки или выбор сертификата. Благодаря этой возможности сертификаты программного обеспечения и оборудования или смарт-карты используются для идентификации в приложении. Эта возможность может использоваться вашим работодателем, банком или государственными службами для идентификации. |
Обмен данными, когда ваше приложение не находится на переднем плане
Фоновые задачи предоставляют общие сведения о выполнении работы, если приложение не находится на переднем плане. В частности, ваш код должен предпринимать специальные меры, чтобы получать уведомления, когда он не является текущим приложением на переднем плане и для него по сети поступают данные. Триггеры канала управления поддерживаются в Windows для этой цели. Дополнительные сведения см. в разделе ControlChannelTrigger. Более новая технология обеспечивает более высокую функциональность с меньшими затратами для некоторых сценариев, таких как сокеты потоков с поддержкой push-уведомлений: брокер сокетов и триггеры действий сокетов.
Если приложение использует DatagramSocket, StreamSocket или StreamSocketListener, ваше приложение может передать владение открытым сокетом брокеру сокета, предоставленному системой, а затем оставить передний план или даже завершить работу. Когда подключение выполняется на перенесенном сокете или трафик поступает на этот сокет, то активируется ваше приложение или назначенная фоновая задача. Если приложение не запущено, оно будет запущено. Затем брокер сокетов уведомляет приложение с помощью SocketActivityTrigger о том, что новый трафик прибыл. Приложение забирает сокет обратно у брокера сокетов и обрабатывает трафик через этот сокет. Это означает, что приложение потребляет гораздо меньше системных ресурсов, если он не активно обрабатывает сетевой трафик.
Брокер сокетов предназначен для замены триггеров канала управления, где это применимо, так как он предоставляет те же функции, но с меньшим количеством ограничений и меньшим объемом памяти. Брокер сокетов может использоваться приложениями, которые не являются приложениями экрана блокировки, и он используется одинаково как на телефонах, так и на других устройствах. Приложения не должны работать при поступлении трафика для активации брокером сокетов. И брокер сокетов поддерживает прослушивание TCP-сокетов, чего не поддерживают триггеры канала управления.
Выбор сетевого триггера
Существуют некоторые сценарии, в которых любой тип триггера подходит. При выборе типа триггера, используемого в приложении, рассмотрите следующие советы.
- Если вы используете IXMLHTTPRequest2, System.Net.HttpClient или System.Net.Http.HttpClientHandler, необходимо использовать ControlChannelTrigger.
- Если вы используете StreamSockets с поддержкой push-уведомлений, можно использовать триггеры канала управления, но следует предпочесть SocketActivityTrigger. Последний выбор позволяет системе освободить память и уменьшить требования к мощности, если подключение не используется.
- Если вы хотите свести к минимуму объем памяти приложения, если оно не активно обслуживает сетевые запросы, по возможности предпочтете SocketActivityTrigger .
- Если вы хотите, чтобы приложение могло получать данные во время работы системы в режиме ожидания подключения, используйте SocketActivityTrigger.
Дополнительные сведения и примеры использования брокера сокетов см. в разделе "Сетевые коммуникации" в фоновом режиме.
Защищенные подключения
Безопасный уровень сокетов (SSL) и более поздний протокол TLS — это криптографические протоколы, предназначенные для проверки подлинности и шифрования для сетевого взаимодействия. Эти протоколы предназначены для предотвращения перехвата и изменения при отправке и получении сетевых данных. Эти протоколы используют модель клиентского сервера для обмена протоколами. Эти протоколы также используют цифровые сертификаты и центры сертификации, чтобы убедиться, что сервер является тем, кто он утверждает.
Создание защищённых сокетных соединений
Объект StreamSocket можно настроить для обмена данными между клиентом и сервером с помощью SSL/TLS. Эта поддержка SSL/TLS ограничена использованием объекта StreamSocket в качестве клиента в согласовании SSL/TLS. Вы не можете использовать SSL/TLS с StreamSocket , созданным StreamSocketListener при получении входящих сообщений, так как согласование SSL/TLS в качестве сервера не реализуется классом StreamSocket .
Существует два способа защиты подключения StreamSocket с помощью SSL/TLS:
- ConnectAsync — сделайте начальное подключение к сетевой службе и немедленно согласовывайте использование SSL/TLS для всех подключений.
- UpgradeToSslAsync — изначально подключитесь к сетевой службе без шифрования. Приложение может отправлять или получать данные. Затем обновите подключение, чтобы использовать SSL/TLS для всех дальнейших подключений.
SocketProtectionLevel указывает требуемый уровень защиты сокета, с которым приложение хочет установить или обновить подключение. Однако конечный уровень защиты установленного соединения определяется в процессе согласования между обеими конечными точками подключения. Результатом может быть более низкий уровень защиты, чем указанный, если другая конечная точка запрашивает более низкий уровень.
После успешного завершения асинхронной операции можно получить запрошенный уровень защиты, используемый в вызове ConnectAsync или UpgradeToSslAsync через свойство StreamSocketInformation.ProtectionLevel . Однако это не отражает фактический уровень защиты, который использует подключение.
Note
Код не должен неявно зависеть от использования определенного уровня защиты или от предположения, что заданный уровень безопасности используется по умолчанию. Ландшафт безопасности постоянно изменяется, а протоколы и уровни защиты по умолчанию изменяются со временем, чтобы избежать использования протоколов с известными слабыми местами. Значения по умолчанию могут отличаться в зависимости от конфигурации отдельного компьютера или установленного программного обеспечения и примененных исправлений. Если приложение зависит от использования определенного уровня безопасности, необходимо явно указать этот уровень, а затем убедиться, что он фактически используется для установленного подключения.
Использование ConnectAsync
ConnectAsync можно использовать для установления первоначального подключения к сетевой службе, а затем немедленно согласовывать использование SSL/TLS для всех подключений. Существует два метода ConnectAsync , поддерживающие передачу параметра protectionLevel :
- ConnectAsync(EndpointPair, SocketProtectionLevel) — запускает асинхронную операцию в объекте StreamSocket для подключения к удаленному назначению сети, указанному как объект EndpointPair и SocketProtectionLevel.
- ConnectAsync(HostName, String, SocketProtectionLevel) — запускает асинхронную операцию в объекте StreamSocket для подключения к удаленному назначению, указанному именем удаленного узла, именем удаленной службы и SocketProtectionLevel.
Если для параметра protectionLevel задано значение Windows. Networking.Sockets.SocketProtectionLevel.Ssl при вызове любого из указанных выше методов ConnectAsync, StreamSocket будет установлен для использования SSL/TLS для шифрования. Это значение требует шифрования и никогда не позволяет использовать шифр NULL.
Обычная последовательность, используемая с одним из этих методов ConnectAsync , совпадает.
- Создайте StreamSocket.
- Если требуется дополнительный параметр сокета, используйте свойство StreamSocket.Control , чтобы получить экземпляр StreamSocketControl , связанный с объектом StreamSocket . Задайте свойство в StreamSocketControl.
- Вызовите один из приведенных выше методов ConnectAsync , чтобы запустить операцию для подключения к удаленному назначению и немедленно согласовать использование SSL/TLS.
- Фактически согласованный при использовании ConnectAsync уровень SSL-защиты можно определить, получив значение свойства StreamSocketInformation.ProtectionLevel после успешного завершения асинхронной операции.
В следующем примере создается объект StreamSocket и предпринимается попытка установить подключение к сетевой службе и сразу согласовать использование SSL/TLS. Если согласование выполнено успешно, все сетевое взаимодействие с помощью StreamSocket между клиентом сетевого сервера будет зашифровано.
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
Используйте UpgradeToSslAsync
Когда ваш код использует UpgradeToSslAsync, он сначала устанавливает незашифрованное подключение к сетевой службе. Приложение может отправлять или получать некоторые данные, а затем обновить подключение, чтобы использовать SSL/TLS для всех дальнейших коммуникаций.
Метод UpgradeToSslAsync принимает два параметра. Параметр protectionLevel указывает требуемый уровень защиты. Параметр validationHostName — это имя узла удаленного назначения сети, которое используется для проверки при обновлении до SSL. Как правило, имя узла проверкиHostName совпадает с именем узла, которое приложение использовало для первоначального установления подключения. Если для параметра protectionLevel задано значение Windows. System.SocketProtectionLevel.Ssl при вызове UpgradeToSslAsyncStreamSocket должен использовать SSL/TLS для шифрования для дальнейшего обмена данными по сокету. Это значение требует шифрования и никогда не позволяет использовать шифр NULL.
Обычная последовательность, используемая с методом UpgradeToSslAsync , выглядит следующим образом:
- Создайте StreamSocket.
- Если требуется дополнительный параметр сокета, используйте свойство StreamSocket.Control , чтобы получить экземпляр StreamSocketControl , связанный с объектом StreamSocket . Задайте свойство в StreamSocketControl.
- Если все данные должны быть отправлены и получены незашифрованными, отправьте его сейчас.
- Вызовите метод UpgradeToSslAsync , чтобы запустить операцию обновления подключения для использования SSL/TLS.
- Фактически согласованный с помощью UpgradeToSslAsync уровень SSL можно определить, получив значение свойства StreamSocketInformation.ProtectionLevel после успешного завершения асинхронной операции.
В следующем примере создается StreamSocket, пытается установить подключение к сетевой службе, отправляет некоторые исходные данные, а затем согласовывает использование SSL/TLS. Если согласование выполнено успешно, все сетевое взаимодействие с помощью StreamSocket между клиентом и сетевым сервером будет зашифровано.
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;
}
});
Создание безопасных подключений WebSocket
Как и традиционные подключения сокетов, подключения WebSocket также можно шифровать с помощью протокола TLS/SSL при использовании функций StreamWebSocket и MessageWebSocket для приложения Windows. В большинстве случаев вы хотите использовать безопасное подключение WebSocket. Это приведет к увеличению вероятности успешного подключения, так как многие прокси-серверы отклонят незашифрованные подключения WebSocket.
Примеры того, как создать защищённое сокетное соединение с сетевой службой или обновить существующее соединение до защищённого, см. в статье Как защитить подключения WebSocket с помощью TLS/SSL.
Помимо шифрования TLS/SSL, сервер может потребовать значение заголовка Sec-WebSocket-Protocol для завершения первоначального рукопожатия. Это значение, представленное свойствами StreamWebSocketInformation.Protocol и MessageWebSocketInformation.Protocol , указывает версию протокола подключения и позволяет серверу правильно интерпретировать открывающее подтверждение и обмен данных после этого. Используя эти сведения о протоколе, если в любой момент сервер не может интерпретировать входящие данные безопасным образом, подключение можно закрыть.
Если исходный запрос клиента либо не содержит этого значения, либо содержит значение, не соответствующее ожидаемому сервером, то при ошибке рукопожатия WebSocket сервер отправляет клиенту ожидаемое значение.
Аутентификация
Как предоставить учетные данные для аутентификации при сетевом подключении.
Предоставление сертификата клиента с помощью класса StreamSocket
Класс Windows.Networking.Sockets.StreamSocket поддерживает использование SSL/TLS для проверки подлинности сервера, с которым взаимодействует приложение. В некоторых случаях приложение также должно пройти проверку подлинности на сервере с помощью сертификата клиента TLS. В Windows 10 можно указать сертификат клиента в объекте StreamSocket.Control (необходимо задать перед началом подтверждения TLS). Если сервер запрашивает сертификат клиента, Windows ответит на предоставленный сертификат.
Ниже приведен фрагмент кода, показывающий, как реализовать это:
var socket = new StreamSocket();
Windows.Security.Cryptography.Certificates.Certificate certificate = await GetClientCert();
socket.Control.ClientCertificate = certificate;
await socket.ConnectAsync(destination, SocketProtectionLevel.Tls12);
Предоставление учетных данных проверки подлинности веб-службе
Сетевые API, позволяющие приложениям взаимодействовать с безопасными веб-службами, каждый предоставляет собственные методы для инициализации клиента или задания заголовка запроса с учетными данными проверки подлинности сервера и прокси-сервера. Каждый метод устанавливается с объектом PasswordCredential , указывающим имя пользователя, пароль и ресурс, для которого используются эти учетные данные. В следующей таблице представлено сопоставление этих API:
Обработка сетевых исключений
В большинстве областей программирования исключение указывает на значительную проблему или сбой, вызванный некоторыми недостатками в программе. В сетевом программировании существует дополнительный источник исключений: сама сеть и характер сетевого взаимодействия. Сетевые коммуникации по сути ненадежны и подвержены неожиданному сбою. Для каждого из способов использования сети приложение должно поддерживать некоторые сведения о состоянии; и код приложения должен обрабатывать сетевые исключения, обновляя эти сведения о состоянии и инициируя соответствующую логику для повторного установления или повторения сбоев связи.
Когда универсальные Windows приложения вызывают исключение, обработчик исключений может получить более подробную информацию о причине исключения, чтобы лучше понять ошибку и принять соответствующие решения.
Каждая проекция языка поддерживает метод для получения более подробных сведений. Исключение представляется как значение HRESULT в универсальных приложениях Windows. Файл Winerror.h содержит очень большой список возможных значений HRESULT , включая сетевые ошибки.
Сетевые API поддерживают различные методы получения подробных сведений о причине исключения.
- Некоторые API предоставляют вспомогательный метод, который преобразует значение HRESULT из исключения в значение перечисления.
- Другие API предоставляют метод для получения фактического значения HRESULT .
Windows developer