如何使用 StreamWebSocket 进行连接 (HTML)

[ 本文适用于编写 Windows 运行时应用的 Windows 8.x 和 Windows Phone 8.x 开发人员。如果你要针对 Windows 10 进行开发,请参阅 最新文档 ]

本主题向你展示 如何使用 Windows 运行时应用中的 StreamWebSocket 发送和接收数据流。

StreamWebSocket 类提供了基于消息的 WebSocket 协议的基于流的抽象。这在以下场景中非常有用:需要在客户端和服务器之间传输较大文件(如照片或影片)。该服务器必须支持 WebSocket 协议。使用 StreamWebSocket 将允许使用每个读取操作读取消息各部分,而不要求在单个操作中读取整个消息(如使用 MessageWebSocket 一样)。

StreamWebSocket 类仅支持二进制消息。对于 UTF-8 消息,必须使用 MessageWebSocket

先决条件

以下示例使用 JavaScript,且基于 WebSocket 示例。 有关创建使用 JavaScript 的 Windows 运行时应用的常规帮助,请参阅创建你的第一个使用 JavaScript 的 Windows 运行时应用。此外,在本主题中使用 JavaScript Promise 来完成异步操作。有关此编程模式的详细信息,请参阅在 JavaScript 中使用 Promise 进行异步编程

为了使你的 Windows 运行时应用能够使用网络,你必须设置在项目 Package.appxmanifest 文件中所需的任何网络功能。 如果你的应用需要作为客户端连接到 Internet 上的远程服务,则“Internet (客户端)”功能是必需的。如果应用需要作为客户端连接到家庭网络或工作网络上的远程服务,则“家庭/工作网络”****功能是必需的。

注意  在 Windows Phone 上,只存在一种网络功能(“Internet (客户端和服务器)”),该功能支持对该应用的所有网络访问。

 

有关详细信息,请参阅如何设置网络功能

说明

1. 创建一个 StreamWebSocket 对象来发送和接收数据

此部分中的代码将创建一个新 StreamWebSocket,连接到 WebSocket 服务器,将数据发送到服务器,然后侦听响应。

我们首先验证要使用的服务器 URI 是否有效。然后使用该 URI 连接到 WebSocket 服务器并等待接收来自该服务器的响应。

首先检查输入 URI 地址,以确保用户传递了有效的 URI 地址。如果应用已知道该 URI 适用于 WebSocket 服务器,则不需要此步骤。

当统一资源标识符 (URI) 的无效字符串传递到 Windows.Foundation.Uri 对象的构造函数时,会引发异常。

使用 JavaScript 时,没有可用于试用字符串和将其解析到 URI 的方法。若要在这种情况下捕获此异常,请在构造 URI 构造的位置在代码周围使用 try/catch 块。

如果这些方案是仅受 StreamWebSocket 支持的方案,则该示例还应该检查 URI 中的 HTTP 方案是 WS 还是 WSS。

如果我们在用户输入中具有有效 URI,则该应用将连接到 WebSocket 服务器并可以发送和接收数据。

随时可能由网络错误(例如连接中断、连接失败和 HTTP 服务器失败)引发异常。这些错误将引发异常。如果应用不处理异常,它可能导致整个应用在运行时终止。 当你调用大部分异步网络方法时,必须编写代码以处理异常。有时,如果发生异常,可以重试网络方法来尝试解决问题。其他时候,应用可能需要计划使用之前的缓存数据在没有网络连接的情况下继续工作。有关处理网络异常的详细信息,请参阅处理网络应用中的异常

注意  你可能想要向用户显示消息或者写入已发生事件的日志(例如,建立连接或发生错误时)。该示例将调用实现你的应用所需的 displayStatus 函数。

 

注意  用于执行写入和读取操作的 writeOutgoing()readIncoming() 函数将在后续步骤中进行定义。

 

  • 打开 js 文件夹。打开你正在使用的 .js 文件,并添加以下代码。

    
    // Define some variables we will use
    var streamWebSocket;
    var dataWriter;
    var dataReader;
    // The data to send
    var data = "Hello World";
    var countOfDataSent;
    var countOfDataReceived;
    
    function start() {
       if (streamWebSocket) {
          // The WebSocket is already running. Go ahead and immediately return,  
          // or display a message that indicates that it is running.
          return;
       }
    
       var webSocket = new Windows.Networking.Sockets.StreamWebSocket();
       webSocket.onclosed = onClosed;
    
       // WebSocket server to test connections
       // If the scheme is wss:, then the server will
       // echo back what it receives
       var uriString = "wss://echo.websocket.org";
    
       // We might get the uriString from the user so
       // we need to check that we have a valid URI
       var serverUri;
       try {
          serverUri = new Windows.Foundation.Uri(uriString);
          }
       catch (Exception) {
          displayStatus("Invalid URI, please re-enter a valid URI.");
          return;
       }
    
       if (serverUri.schemeName != "ws" && serverUri.schemeName != "wss") {
          displayStatus("Only 'ws' and 'wss' schemes supported. Please re-enter URI");
          return;
       }
    
       // Asynchronous networking methods can throw execptions
       webSocket.connectAsync(uri).done(function () {
          diaplayStatus("Connected");
    
          streamWebSocket = webSocket;
          dataWriter = new Windows.Storage.Streams.DataWriter(webSocket.outputStream);
          dataReader = new Windows.Storage.Streams.DataReader(webSocket.inputStream);
          // When buffering, return as soon as any data is available.
          dataReader.inputStreamOptions = Windows.Storage.Streams.InputStreamOptions.partial;
          countOfDataSent = 0;
          countOfDataReceived = 0;
    
          // Continuously send data to the server
          writeOutgoing();
    
          // Continuously listen for a response
          readIncoming();
    
       }, function (error) {
          var errorStatus = Windows.Networking.Sockets.WebSocketError.getStatus(error.number);
          if (errorStatus === Windows.Web.WebErrorStatus.cannotConnect ||
             errorStatus === Windows.Web.WebErrorStatus.notFound ||
             errorStatus === Windows.Web.WebErrorStatus.requestTimeout) {
             displayStatus("Cannot connect to the server");
          } else {
             displayStatus("Failed to connect: " + getError(error));
          }
       });
    }
    

2. 发送传出数据

此部分中的代码允许你的 WebSocket 对象将数据发送到服务器。

注意  writeError() 函数将在后续步骤中定义。

 

  • 在你的 .js 文件中添加下列代码以定义 writeOutgoing() 函数。

    function writeOutgoing() {
       try {
          var size = dataWriter.measureString(data);
          countOfDataSent += size;
    
          dataWriter.writeString(data);
          dataWriter.storeAsync().done(function () {
             // Add a 1 second delay so the user can see what's going on.
             setTimeout(writeOutgoing, 1000);
          }, writeError);
       }
       catch (error) {
          displayStatus("Sync write error: " + getError(error));
       }
    }
    

3. 读取传入数据

此部分中的代码允许你的 WebSocket 对象从服务器读取数据。

注意  readError() 函数将在后续步骤中定义。

 

  • 在你的 .js 文件中添加下列代码以定义 readIncoming() 函数。

    
    function readIncoming(args) {
       // Buffer as much data as you require for your protocol.
       dataReader.loadAsync(100).done(function (sizeBytesRead) {
          countOfDataReceived += sizeBytesRead;
    
          var incomingBytes = new Array(sizeBytesRead);
          dataReader.readBytes(incomingBytes);
    
          // Do something with the data.
          // Alternatively you can use DataReader to read out individual booleans,
          // ints, strings, etc.
    
          // Start another read.
          readIncoming();
       }, readError);
    }
    

4. 添加错误处理代码

  • 当你调用大部分异步网络方法时,必须编写代码以处理异常。异常处理程序可以检索关于异常原因的更详细的信息,以更好地了解此次失败,并作出适当的判定。有关详细信息,请参阅如何处理网络应用中的异常

    将代码添加至你的 .js 文件以定义 writeError()readError() 函数,从而分别记录写入和读取错误日志(或采取其他操作)。你所使用的具体实现操作可能会有所不同。

    
    function writeError(error) {
       // Add your code to handle write errors.
    }
    
    function readError(error) {
       // Add your code to handle read errors.
    }
    

5. 为 StreamWebSocket.Closed 事件注册回调

发生 StreamWebSocket.Closed 事件时,会调用所注册的回调并接收来自 WebSocketClosedEventArgs 的数据以关闭连接。

  • 将以下代码添加到 .js 文件中。

    function onClosed(args) {
       // You can add code to log or display the code and reason
       // for the closure (stored in args.code and args.reason)
       if (streamWebSocket) {
          streamWebSocket.close();
       }
       streamWebSocket = null;
    }
    

摘要和后续步骤

在本教程中,我们已了解如何连接到 WebSocket 服务器以及如何使用 StreamWebSocket 发送和接收数据。

有关展示如何使用 WebSockets 发送和接收数据的完整示例,请参阅 WebSocket 示例

相关主题

其他

使用 JavaScript 中的 Promises 进行异步编程

使用 WebSocket 进行连接

创建你的第一个使用 JavaScript 的 Windows 运行时应用

如何使用 MessageWebSocket 进行连接

如何处理网络应用中的异常

如何设置网络功能

参考

StreamWebSocket

Windows.Networking.Sockets

示例

WebSocket 示例