源码地址: github
建议阅读时间: 1 hour
在学习websocket中,查阅了大量的中英文资料,这里将成果分享给大家?
Websocket
websocket官网: websocket官网
1. websocket简介:
WebSocket是HTML5开始提供的一种在单个TCP连接上进行全双工通讯的协议。websocket使得客户端和服务器之间的数据交换变得更加简单,允许服务端主动向客户端推送数据。在WebSocket API中,浏览器和服务器只需要完成一次握手,两者之间就直接可以创建持久性的链接,并进行双向数据传输
网站推送技术:
Ajax轮询,在特定的时间间隔,由浏览器对服务器发出HTTP请求,然后由服务端返回最新的数据给客户端的浏览器。(缺点是浏览器需要不断的向服务器发出请求,然后HTTP请求可能包含较长的头部,其中真正有效的数据可能只是很小的一部分,这样会浪费很多的带宽等资源)
websocket document:
websocket的优点:
HTML5定义的WebSocket协议,能更好的节省服务器资源和带宽,并且能够更实时地进行通讯一开始的握手需要借助http请求完成,HTTP协议只是在建立连接时使用,建立连接后通过TCP协议传输,不再需要HTTP协议。通过WebSocket的长连接,客户端和服务端可以进行大量的数据传输而不会带来相关的性能问题,这给Web端带来了极大的功能增强。
目前Web端可以使用WebSocket来进行IM相关功能开发,或者实时协作等需要与服务器进行大量数据交互的功能,并且不需要像之前一样使用长轮询的Hack方式来实现
浏览器通过javascript向服务器发出建立WebSocket连接的请求,连接建立以后,客户端和服务端就可以通过TCP连接直接交换数据。当你获取WebSocket连接后,你可以通过send()方法来向服务器发送数据,并通过onmessage事件来接收服务器返回的数据
websocket API
var socket = new WebSocket(url, [protocol]);
url: 指定连接的URL
protocol: 可选的,指定了可接受的子协议```
WebSocket事件
open Socket.onopen 连接建立时触发
message Socket.onmessage 客户端接收服务端数据时触发
error Socket.onerror 通信发生错误时触发
close Socket.onclose 连接关闭时触发
WebSocket方法
Socket.send() 使用连接发送数据
Socket.close() 关闭连接
2. websocket初步使用
使用js脚本建立websocket连接,并交互数据:
我们服务端使用的是官网的给出的地址,此处简单实现客户端
demo1:
index.html
官网示例: websocket官网示例
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Websocket</title>
</head>
<body>
<h1>Echo Test</h1>
<input type="text" id="sendTxt">
<button id="sendBtn">发送</button>
<div id="recv"></div>
<script>
// 官方提供的websocket server地址
var websocket = new WebSocket("ws://echo.websocket.org/");
// Socket.onopen 事件 连接建立时触发
websocket.onopen = function() {
console.log('websocket open');
document.getElementById('recv').innerHTML = "Connected";
}
// 连接关闭时触发
websocket.onclose = function() {
console.log('websocket close');
}
// 客户端接收服务端数据时触发 e是MessageEvent
websocket.onmessage = function(e) {
console.log(e.data);
document.getElementById("recv").innerHTML = e.data;
}
document.getElementById("sendBtn").onclick = function() {
var txt = document.getElementById("sendTxt").value;
websocket.send(txt);
}
</script>
</body>
</html>
3. 使用node.js搭建自己的websocket server服务器
我们知道后端语言非常的多,有很多种对websocket支持的服务器
如下所示:
php - http://code.google.com/p/phpwebsocket/
jetty - http://jetty.codehaus.org/jetty/(版本7开始支持websocket)
netty - http://www.jboss.org/netty
ruby - http://github.com/gimite/web-socket-ruby
Kaazing - https://web.archive.org/web/20100923224709/http://www.kaazing.org/confluence/display/KAAZING/Home
Tomcat - http://tomcat.apache.org/(7.0.27支持websocket,建议用tomcat8,7.0.27中的接口已经过时)
WebLogic - http://www.oracle.com/us/products/middleware/cloud-app-foundation/weblogic/overview/index.html(12.1.2開始支持)
node.js - https://github.com/Worlize/WebSocket-Node
node.js - http://socket.io
nginx - http://nginx.com/
mojolicious - http://mojolicio.us/
python - https://github.com/abourget/gevent-socketio
Django - https://github.com/stephenmcd/django-socketio
erlang - https://github.com/ninenines/cowboy.git
Node.js简介
Node.js是一个基于Chrome V8引擎的JavaScript运行环境。使用了一个事件驱动、非阻塞式I/O的模型,使其轻量又高效。我们可以使用nodejs搭建websocket服务器
开发环境: 我使用的是ubuntu linux(windows官网自行下载), 以及nodejs-websocket模块
文档地址:
官网: official website
参考文档: nodejs github nodejs-websocket — a node.js module for websocket server and client 官方文档翻译的中文博客
ubuntu安装nodejs、 npm、以及nodejs-websocket
注: 使用Ubuntu apt-get安装nodejs,版本太低,建议使用源码安装,或者换源参考博客
在Github上获取Node.js源码:
$ sudo git clone https://github.com/nodejs/node.git
Cloning into 'node'...
修改目录权限:
$ sudo chmod -R 755 node
使用./configure创建编译文件:
$ cd node
$ sudo ./configure
$ sudo make
$ sudo make install
查看node版本:
$ node --version
v12.0.0-pre
安装nodejs-websocket模块
npm install nodejs-websocket
启动wsServer.js进程,注杀死node进程可以使用(pkill node、tskill node):
$ node wsServer.js
4. 实现简单聊天室并优化
demo2:
wsServer.js
如下
var ws = require("nodejs-websocket");
// Scream server example : "hi" -> "HI!!!" 将用户从表单传入的字符串转化为大写字母传送给用户
const hostname = 'xxx.xxx.xxx.xxx';
const port = 8001;
// Scream server example : "hi" -> "HI!!!"
var server = ws.createServer(function(conn) {
console.log('Server running at ws://%s:%d/', hostname, port);
conn.on("text", function(str) {
console.log("Received" + str);
conn.sendText