Marvin's Blog【程式人生】

Ability will never catch up with the demand for it

21 Apr 2020

UWP开发文档【二】:网络相关

Develop Apps > Communications > Networking and web services

Networking basics

App的联网能力是受管控的,有三种能力声明:

  • internetClient,可以访问公共网络
  • internetClientServer,可以作为公共网络的服务器
  • privateNetworkClientServer,可以在私有网络(家、公司)等作为客户端和服务器

一些相关的,但是不常用的能力声明:

  • enterpriseAuthentication,允许应用使用域账号访问受限资源。有此能力的应用可以在域管控的网络上代表用户访问资源。
  • proximity,在近场通信使用
  • sharedUserCertificates,允许访问用户的软件或者硬件证书(比如smart card上的证书)

当应用处于后台时,必须注册后台任务才能处理进来的网络数据。历史上使用Control Channel Trigger作为后台任务的触发。Win10提供了一些额外的机制,比如push-enabled stream sockets提供的socket broker以及socket activity trigger。

如果你的应用使用了DatagramSocket, StreamSocket, 或者StreamSocketListener。那么在进入后台的时候可以把socket转交给系统的socket broker处理。当有数据进来的时候,socket broker会触发(比如使用SocketActivityTrigger)相应的后台任务,这时候应用可以接过socket来处理其中的数据。

socket broker在很多场景可以替代Control Channel Triggers。socket broker有很多好处,比如节省系统资源,可以侦听TCP,可以在Connected Standby模式工作。但是也有缺点,比如不能在Lock Screen应用中使用。

选择相应的网络触发器:

  • 如果使用 IXMLHTTPRequest2、System.Net.Http.HttpClient 或者System.Net.Http.HttpClientHandler,,必须使用Control Channel Trigger
  • 如果使用push-enabled StreamSockets,可以使用Control Channel Trigger,但是最好使用SocketActivityTrigger。

Control Channel Trigger

Network communications in the background

StreamSocket可以配置使用SSL/TLS。但是通过StreamSocketListener创建的StreamSocket无法主动配置SSL/TLS,因为这时候连接已经建立起来了。

配置SSL/TLS有两种办法:

  • ConnectAsync ,一开始就使用SSL/TLS
  • UpgradeToSslAsync,一开始不适用,但是后来升级到SSL/TLS。

StreamSocket的SocketProtectionLevel需要通信双方共同决定,所以实际生效的会比预设的要低。也就是说StreamSocketinformation.ProtectionLevel 反映的不是真实使用的保护级别。

例子:

和普通的socket一样,WebSocket(StreamWebSocket和MessageWebSocket)也可以使用SSL/TLS来加密。具体的例子参考How to secure WebSocket connections with TLS/SSL

Websocket使用了Sec-WebSocket-Protocol来指明协议信息。这个会在StreamWebSocketInformation.Protocol和MessageWebSocketInformation.Protocol 部属中体现。

StreamSocket支持SSL/TLS验证。但是有时候,应用自身也要使用TLS向服务端做验证。在Win10,可以通过StreamSocket.Control来提供客户端证书。也就是当服务端要求的时候,Windows会把StreamSocket.Control的证书提供给服务端。示例如下:

var socket = new StreamSocket();
Windows.Security.Cryptography.Certificates.Certificate certificate = await GetClientCert();
socket.Control.ClientCertificate = certificate;
await socket.ConnectAsync(destination, SocketProtectionLevel.Tls12);

通过将PasswordCredential设置到通信协议的部属中,可以对该通信协议提供验证信息,如下所示:

  • WebSockets
    • MessageWebSocketControl.ServerCredential
    • MessageWebSocketControl.ProxyCredential
    • StreamWebSocketControl.ServerCredential
    • StreamWebSocketControl.ProxyCredential
  • Background Transfer
    • BackgroundDownloader.ServerCredential
    • BackgroundDownloader.ProxyCredential
    • BackgroundUploader.ServerCredential
    • BackgroundUploader.ProxyCredential
  • Syndication
    • SyndicationClient(PasswordCredential)
    • SyndicationClient.ServerCredential
    • SyndicationClient.ProxyCredential
  • AtomPub
    • AtomPubClient(PasswordCredential)
    • AtomPubClient.ServerCredential
    • AtomPubClient.ProxyCredential

在网络通信中,出现异常是常见的事情。代码必须要准备好处理这些异常。错误通常用HRESULT表示。在Winerror.h中,包含了一个HRESULT可能值的大列表。处理通信的API提供了一些额外的帮助用来处理HRESULT。更多参考Networking API Improvements in Windows 10

HttpClient

  • Windows.Web.Http
  • Windows.Web.Http.Headers
  • Windows.Web.Http.Filters

这三个命名空间中runtimeclass用来支持UWP对HTTP的处理,包括的功能如下:

  • 支持 GET, PUT, POST以及DELETE
  • 支持常见验证配置和模式
  • 可以访问SSL细节
  • 可以包含自定义的filter
  • 可以操纵cookies
  • 提供异步操作的进度条信息

HttpClient对应的请求和回复为:

  • HttpRequestMessage
  • HttpRespsonseMessage

上面消息的内容在RFC 2616中定义。

Windows.Web.Http抽象出来的http内容包括http的body、headers以及cookies。http内容可以与一个HTTP请求或者HTTP回复关联。

Windows.Web.Http包括下面工具:

  • HttpBufferContent,http内容作为buffer
  • HttpFormUrlEncodedContent,一个包括键值对的集合,以application/x-www-form-urlencoded MIME方式编码
  • HttpMultipartContent,以multipart/* MIME类型组织的内容
  • HttpMultipartFormDataContent,内容以multipart/form-data MIME方式组织
  • HttpStreamContent,以流的方式组织内容,这是HTTP GET和POST内部使用的类型
  • HttpStringContent,以字符串方式组织内容
  • IHttpContent,接口,可供开发者提供自己的内容组织方式

Windows.Web.Http.Headers 所包含的类型可以用来创建HTTP头以及cookies,创建出来的对象通常作为HttpRequestMessage和HttpResponse对象的部属.

代码示例:

        // Send the GET request.
       httpResponseMessage = httpClient.GetAsync(requestUri).get();
       httpResponseMessage.EnsureSuccessStatusCode();
       httpResponseBody = httpResponseMessage.Content().ReadAsStringAsync().get();

POST binary data over HTTP阐述如何发送二进制数据。

POST JSON data over HTTP阐述如何发送JSON数据。

对于错误的URI,WinRT会抛出一个异常。在C++中,这个异常在创建Windows.Foundation.Uri时候抛出。

对于大部分参数错误,HRESULT返回E_INVALIDARG。对于一些不支持的函数调用,返回的是E_ILLEGAL_METHOD_CALL。

(本篇完)

comments powered by Disqus