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的聊天客户端 <script> window.onload = function() { // 关心一些UI细节 var nick = prompt("Enter your nickname"); // 获取用户昵称 var input = document.getElementById("input"); // 査找input字段 input.focus(); // 设置光标 // 打开一个WebSocket,用于发送和接收聊天消息 // 假设下载的HTTP服务器作为WebSockem务器运作,并且使用同样的主机名和端口 // 只是协议由htttp://变成ws:// var socket = new WebSocket("ws://" + location.host + "/"); // 下面展示了如何通过WebSocket从服务器获取消息 socket.onmessage = function(event) { // 当收到一条消息 var msg = event.data; // 从事件对象中获取消息内容 var node = document.createTextNode(msg); // 将它标记为一个文本节点 var div = document.createElement("div"); // 创建一个<div> div.appendChild(node); // 将文本节点添加到该div中 document.body.insertBefore(div, input); // 在input前添加该div input.scrollIntoView(); // 确保输入框可见 } // 下面展示了如何通过WebSocket发送消息给服务器端 input.onchange = function() { // 当用户敲击回车键 var msg = nick + ": " + input.value; // 用户昵称加上用户的输入 socket.send(msg); // 通过套接字传递该内容 input.value = ""; // 等待更多内容的输入 } }; </script> <!-- 聊天窗口UI很简单,一个宽的文本输入域 --> <!-- 新的聊天消息会插入在该元素中 --> <input id="input" style="width:100%"/>
下例是一个基于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);