WebSocket入门
一、为什么需要 WebSocket?
WebSocket 是一种网络通信协议,很多高级功能都需要它。
初次接触 WebSocket 的人,都会问同样的问题:我们已经有了 HTTP 协议,为什么还需要另一个协议?它能带来什么好处?
答案很简单,因为 HTTP 协议有一个缺陷:通信只能由客户端发起。
举例来说,我们想了解今天的天气,只能是客户端向服务器发出请求,服务器返回查询结果。HTTP 协议做不到服务器主动向客户端推送信息。
这种单向请求的特点,注定了如果服务器有连续的状态变化,客户端要获知就非常麻烦。我们只能使用"轮询":每隔一段时候,就发出一个询问,了解服务器有没有新的信息。最典型的场景就是聊天室。
轮询的效率低,非常浪费资源(因为必须不停连接,或者 HTTP 连接始终打开)。因此,工程师们一直在思考,有没有更好的方法。WebSocket 就是这样发明的。
二、简介
WebSocket 协议在2008年诞生,2011年成为国际标准。所有浏览器都已经支持了。
它的最大特点就是,服务器可以主动向客户端推送信息,客户端也可以主动向服务器发送信息,是真正的双向平等对话,属于服务器推送技术的一种。
其他特点包括:
(1)建立在 TCP 协议之上,服务器端的实现比较容易。
(2)与 HTTP 协议有着良好的兼容性。默认端口也是80和443,并且握手阶段采用 HTTP 协议,因此握手时不容易屏蔽,能通过各种 HTTP 代理服务器。
(3)数据格式比较轻量,性能开销小,通信高效。
(4)可以发送文本,也可以发送二进制数据。
(5)没有同源限制,客户端可以与任意服务器通信。
(6)协议标识符是ws
(如果加密,则为wss
),服务器网址就是 URL。
ws://example.com:80/some/path
三、客户端的简单示例
WebSocket 的用法相当简单。
下面是一个网页脚本的例子(点击这里看运行结果),基本上一眼就能明白。
var ws = new WebSocket("wss://echo.websocket.org");ws.onopen = function(evt) { console.log("Connection open ..."); ws.send("Hello WebSockets!"); };ws.onmessage = function(evt) {console.log( "Received Message: " + evt.data);ws.close(); };ws.onclose = function(evt) {console.log("Connection closed."); };
四、客户端的 API
WebSocket 客户端的 API 如下。
4.1 WebSocket 构造函数
WebSocket 对象作为一个构造函数,用于新建 WebSocket 实例。
var ws = new WebSocket('ws://localhost:8080');
执行上面语句之后,客户端就会与服务器进行连接。
实例对象的所有属性和方法清单,参见这里。
4.2 webSocket.readyState
readyState
属性返回实例对象的当前状态,共有四种。
- CONNECTING:值为0,表示正在连接。
- OPEN:值为1,表示连接成功,可以通信了。
- CLOSING:值为2,表示连接正在关闭。
- CLOSED:值为3,表示连接已经关闭,或者打开连接失败。
下面是一个示例。
switch (ws.readyState) {case WebSocket.CONNECTING:// do somethingbreak;case WebSocket.OPEN:// do somethingbreak;case WebSocket.CLOSING:// do somethingbreak;case WebSocket.CLOSED:// do somethingbreak;default:// this never happensbreak; }
4.3 webSocket.onopen
实例对象的onopen
属性,用于指定连接成功后的回调函数。
ws.onopen = function () {ws.send('Hello Server!'); }
如果要指定多个回调函数,可以使用addEventListener
方法。
ws.addEventListener('open', function (event) {ws.send('Hello Server!'); });
4.4 webSocket.onclose
实例对象的onclose
属性,用于指定连接关闭后的回调函数。
ws.onclose = function(event) {var code = event.code;var reason = event.reason;var wasClean = event.wasClean;// handle close event };ws.addEventListener("close", function(event) {var code = event.code;var reason = event.reason;var wasClean = event.wasClean;// handle close event });
4.5 webSocket.onmessage
实例对象的onmessage
属性,用于指定收到服务器数据后的回调函数。
ws.onmessage = function(event) {var data = event.data;// 处理数据 };ws.addEventListener("message", function(event) {var data = event.data;// 处理数据 });
注意,服务器数据可能是文本,也可能是二进制数据(blob
对象或Arraybuffer
对象)。
ws.onmessage = function(event){if(typeof event.data === String) {console.log("Received data string");}if(event.data instanceof ArrayBuffer){var buffer = event.data;console.log("Received arraybuffer");} }
除了动态判断收到的数据类型,也可以使用binaryType
属性,显式指定收到的二进制数据类型。
// 收到的是 blob 数据 ws.binaryType = "blob"; ws.onmessage = function(e) {console.log(e.data.size); };// 收到的是 ArrayBuffer 数据 ws.binaryType = "arraybuffer"; ws.onmessage = function(e) {console.log(e.data.byteLength); };
4.6 webSocket.send()
实例对象的send()
方法用于向服务器发送数据。
发送文本的例子。
ws.send('your message');
发送 Blob 对象的例子。
var file = document.querySelector('input[type="file"]').files[0]; ws.send(file);
发送 ArrayBuffer 对象的例子。
// Sending canvas ImageData as ArrayBuffer var img = canvas_context.getImageData(0, 0, 400, 320); var binary = new Uint8Array(img.data.length); for (var i = 0; i < img.data.length; i++) {binary[i] = img.data[i]; } ws.send(binary.buffer);
4.7 webSocket.bufferedAmount
实例对象的bufferedAmount
属性,表示还有多少字节的二进制数据没有发送出去。它可以用来判断发送是否结束。
var data = new ArrayBuffer(10000000); socket.send(data);if (socket.bufferedAmount === 0) {// 发送完毕 } else {// 发送还没结束 }
4.8 webSocket.onerror
实例对象的onerror
属性,用于指定报错时的回调函数。
socket.onerror = function(event) {// handle error event };socket.addEventListener("error", function(event) {// handle error event });
五、服务端的实现
WebSocket 服务器的实现,可以查看维基百科的列表。
常用的 Node 实现有以下三种。
- µWebSockets
- Socket.IO
- WebSocket-Node
具体的用法请查看它们的文档,这里不详细介绍了。
六、WebSocketd
下面,我要推荐一款非常特别的 WebSocket 服务器:Websocketd。
它的最大特点,就是后台脚本不限语言,标准输入(stdin)就是 WebSocket 的输入,标准输出(stdout)就是 WebSocket 的输出。
举例来说,下面是一个 Bash 脚本counter.sh
。
#!/bin/bashecho 1 sleep 1echo 2 sleep 1echo 3
命令行下运行这个脚本,会输出1、2、3,每个值之间间隔1秒。
$ bash ./counter.sh 1 2 3
现在,启动websocketd
,指定这个脚本作为服务。
$ websocketd --port=8080 bash ./counter.sh
上面的命令会启动一个 WebSocket 服务器,端口是8080
。每当客户端连接这个服务器,就会执行counter.sh
脚本,并将它的输出推送给客户端。
var ws = new WebSocket('ws://localhost:8080/');ws.onmessage = function(event) {console.log(event.data); };
上面是客户端的 JavaScript 代码,运行之后会在控制台依次输出1、2、3。
有了它,就可以很方便地将命令行的输出,发给浏览器。
$ websocketd --port=8080 ls
上面的命令会执行ls
命令,从而将当前目录的内容,发给浏览器。使用这种方式实时监控服务器,简直是轻而易举(代码)。
更多的用法可以参考官方示例。
- Bash 脚本读取客户端输入的例子
- 五行代码实现一个最简单的聊天服务器
websocketd 的实质,就是命令行的 WebSocket 代理。只要命令行可以执行的程序,都可以通过它与浏览器进行 WebSocket 通信。下面是一个 Node 实现的回声服务greeter.js
。
process.stdin.setEncoding('utf8');process.stdin.on('readable', function() {var chunk = process.stdin.read();if (chunk !== null) {process.stdout.write('data: ' + chunk);} });
启动这个脚本的命令如下。
$ websocketd --port=8080 node ./greeter.js
官方仓库还有其他各种语言的例子。
WebSocket入门相关推荐
- WebSocket入门介绍及编程实战
前言:最近看了几天的WebSocket,从以前的只闻其名,到现在也算是有一点点的了解了.所以就准备用博客记录一下自己的学习过程,希望也能帮助其它学习的人,因为我本人学习的过程中也是参考了很多其它人的博 ...
- rudesocket如何使用_[WebSocket入门]手把手搭建WebSocket多人在线聊天室(SpringBoot+WebS...
前言 本文中搭建了一个简易的多人聊天室,使用了WebSocket的基础特性. 源代码来自老外的一篇好文: 本文内容摘要: 初步理解WebSocket的前后端交互逻辑 手把手使用 SpringBoot ...
- 【小白入门】Socket和webSocket入门 这一篇就够了!用php的Socket自己实现简单webSocket服务器!
这几天研究了下php实现webSocket的方法,网上查了不少博文,涉及到的知识点不少.但却非常值得学,因为这方面典型的应用场景非常的多,消息推送,聊天室,所有需要长连接的地方都会用到它. ...
- 突袭HTML5之WebSocket入门3 - 通信模型socket.io
为什么需要socket.io? node.js提供了高效的服务端运行环境,但是由于浏览器端对HTML5的支持不一,为了兼容所有浏览器,提供卓越的实时的用户体验,并且为程序员提供客户端与服务端一致的编程 ...
- workman php教程_workerman搭建websocket入门教程,简单实用
在物联网控制远程硬件的过程中,实时通信是必不可少的.不用实时通信可不可以呢?当然是可以的,但在实际应用中的体验可能就十分的不好了. 试想一下,一个联网电灯,控制端命令发出去,电灯要2到3秒钟以后才能开 ...
- Spring WebSocket初探2 (Spring WebSocket入门教程)
2019独角兽企业重金招聘Python工程师标准>>> WebSocket前端准备 SockJS: SockJS 是一个浏览器上运行的 JavaScript 库,如果浏览器不支持 W ...
- WebSocket 入门及开源库
转载自公众号:FightingCoder WebSocket 协议和知识 WebSocket是一种在单个TCP连接上进行全双工通信的协议.WebSocket通信协议于2011年被IETF定为标准RFC ...
- WebSocket 入门:简易聊天室
大家好,我是前端西瓜哥,今天我们用 WebSocket 来实现一个简单的聊天室. WebSocket 是一个应用层协议,有点类似 HTTP.但和 HTTP 不一样的是,它支持真正的全双工,即不仅客户端 ...
- JS 服务器推送技术 WebSocket 入门指北
作者: 前端下午茶 公号 / SHERlocked93 最近在工作中遇到了需要服务器推送消息的场景,这里总结一下收集整理WebSocket相关资料的收获. 1. 概述 1.1 服务器推送 WebSo ...
最新文章
- 对javscript中Object.defineProperty的理解
- 基于Android5.0的Camera Framework源码分析 (三)
- u盘安装ubuntu10.04 、11.04 server
- 【杂谈】从医学专业转行到AI,独立完成项目到获得加州理工大学读研推荐,我如何与有三AI结缘...
- 一种可行的简单的Scene结构in cocos2d
- 脂肪粒和淋巴结肿大的外形可否区分
- mysql 取数据 展示_php mysql_fetch_row逐行获取结果集数据并显示在table表格中
- Vue 双向绑定小案例
- html设置功能区菜单,html – 具有“3D”效果的功能区
- python爬虫——与不断变化的页面死磕和更新换代(3)
- hdu3790最短路径问题 (用优先队列实现的)
- 嵌入式 Web Server 温度检测系统
- SteamVR自定义手部抓取姿势
- 我的世界java凋零_我的世界:玩家还原Java版已“消失”的三个结构,造型让人难忘?...
- MyIM2006开发报告2:Tcp连接
- 戴尔硬件服务器,服务器硬件、结构介绍_Intel Xeon E5-2660 v4_服务器x86服务器-中关村在线...
- UnrealEditor-RHI.dll 没有被指定在windows上运行
- FPGA、集创赛记录
- #include<>和#include“”的区别
- 很不错的PERL管道应用
热门文章
- Java Scala 混合编程导致 编译失败 ,【找不到符号】问题解决
- 教你在Excel里做GA的水平百分比图的详细步骤(图文教程)-成为excel大师(1)...
- Table 'barfoo_datacenter_config.parttemplates' doesn't exist------Mysql
- Android数据库升级实例
- mongodb 的windows 下安装
- 如何在网页中动态为模版页的Body添加属性
- 在线设计 html5 表单,html5注册表单制作-表单制作-小程序表单制作
- OAuth2.0认证
- TransactionTemplate和@Transactional注解的区别
- Network Namespace