【HTML5 API】Web套接字


Web套接字

HTTP协议的特性:它是一种无状态的协议,由客户端请求和服务端响应组成。HTTP实际上是相对比较特殊的网络协议。大多数基于因特网(或者局域网)的网络连接通常都包含长连接和基于TCP套接字的双向消息交换。让不信任的客户端脚本访问底层的TCP套接字是不安全的,但是WebSocket API定义了一种安全方案:它允许客户端代码在客户端和支持WebSocket协议的服务器端创建双向的套接字类型的连接。这让某些网络操作会变得更加简单。

WebSocket API的使用非常简单。首先,通过WebSocket()构造函数创建一个套接字:

var socket = new WebSocket("ws://ws.example.com:1234/resource");

WebSocket()构造函数的参数是一个URL,该URL使用ws://协议(或者类似于https://用于安全链接的wss://协议)。该URL指定要连接的主机,还有可能指定端口(WebSocket使用和HTTP以及HTTPS一样的默认端口)和路径或者资源。

创建了套接字之后,通常需要在上面注册一个事件处理程序:

socket.onopen = function(e) { /* 套接字已经连接 */ };
socket.onclose = function(e) { /* 套接字已经关闭.*/ };
socket.onerror = function(e) { /* 出错了 */ };
socket.onmessage = function(e) {
 var message = e.data; /*服务器发送一条消息*/
};

为了通过套接字发送数据给服务器,可以调用套接字的send()方法:

socket.send("Hello, server!");

当前版本的WebSocket API仅支持文本消息,并且必须以UTF-8编码形式的字符串传递给该消息。然而,当前WebSocket协议还包含对二进制消息的支持,未来版本的API可能会允许在客户端和WebSocket服务器端进行二进制数据的交换。

当完成和服务器的通信之后,可以通过调用close()方法来关闭WebSocket。

WebSocket完全是双向的,并且一旦建立了WebSocket连接,客户端和服务器端都可以在任何时候互相传送消息,与此同时,这种通信机制采用的不是请求和响应的形式。每个基于WebSocket的服务都要定义自己的“子协议”,用于在客户端和服务器端传输数据。慢慢的,这些“子协议”也可能发生演变,可能最终要求客户端和服务器端需要支持多个版本的子协议。幸运的是,WebSocket协议包含一种协商机制,用于选择客户端和服务器端都能“理解”的子协议。可以传递一个字符串数组给WebSocket()构造函数。服务器端会将该数组作为客户端能够理解的子协议列表。然后,它会选择其中一个使用,并将它传递给客户端。一旦连接建立之后,客户端就能够通过套接字的protocol属性检测当前在使用的是哪种子协议。

例就是一个简单的聊天客户端:它采用了WebSocket来实现双向通信,而没有使用EventSource来获取消息以及XMLHttpRequest来发送消息。

例:基于WebSocket的聊天客户端


 

 

下例是一个基于WebSocket的聊天服务器,运行在Node中。WebSocket将聊天应用的服务端简化成和客户端一样。

例: 使用WebSocket和Node的聊天服务器
/*
 * 这是运行在NodeJS上的服务器端JavaScript
 * 在HTTP服务器之上,它运行一个WebSocket服务器,该服务器使想来自
 * https://github.com/miksago/node-websocket-server/ 的第三方WebSocket库实现
 * 如果得到"/"的一个HTTP请求,则返回聊天客户端的HTML文件
 * 除此之外任何HTTP请求都返回404
 * 通过WebSocket协议接收到的消息都仅广播给所有激活状态的连接
 */
var http = require('http');	              // 使用Node的HTTP服务器API
var ws = require('websocket-server');     // 使用第三方WebSocket库

// 启动阶段,读取聊天客户端的资源文件
var clientui = require('fs').readFileSync("wschatclient.html");

// 创建一个HTTP服务器
var httpserver = new http.Server();

// 当HTTP服务器获得一个新请求时,运行此函数
httpserver.on("request", function (request, response) {
    // 如果请求"/",则返回客户端聊天UI
    if (request.url === "/") { // 请求聊天UI
        response.writeHead(200, ("Content-Type": "text/html"}); 
        response.write(clientui);
        response.end();
    }
    
    else { //对任何其他的请求返回404"无法找到"编码
        response.writeHead(404);
        response.end();
    }
});

// 在HTTP服务器上包装一个WebSocket服务器
var wsserver = ws.createServer({server: httpserver});

// 当接收到一个新的连接请求的时候,调用此函数
wsserver.on ("connection**, function(socket) (
    socket.send("Welcome to the chat room.");     // 向新客户端打招呼 
    socket.on("message", function(msg) {	     // 监听来自客户端的消息
        wsserver. broadcast (msg);	              // 并将它们广播给每个人
    });
});

// 在8000端口运行服务器。启动WebSocket服务器的时候也会启动HTTP服务器 
// 连接到http://localhost:8000/,并开始使用它
wsserver.listen(8000);