WebSocket入门
[TOC]
1.概念
ws协议,基于TCP连接,随着H5的发展而诞生
允许浏览器和服务器建立持久连接
服务器可以主动给客户端发送信息,双向互通
2.基础组成
基础的组件由/open/close/send/message/error组成并延伸
当然,实际使用时需要有服务器来作为通信支撑,此处以nodejs为例
服务器
首先需要安装nodjs环境
然后使用脚本拉取github的开源服务器model
npm install nodejs-websocket
使用一下方式建立服务器脚本即可(需要与model同层,配置才生效)
wsServer.js
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20
| var ws = require("nodejs-websocket") var port=8000;
var server = ws.createServer(function (conn) { console.log("New connection") conn.on("text", function (str) { console.log("Received "+str) conn.sendText(str.toUpperCase()+"!!!") }) conn.on("close", function (code, reason) { console.log("Connection closed") }) conn.on("error",function(err){ console.log(err) }) }).listen(port)
|
启动方式:node wsServer.js
客户端
以js为例(java/nodejs等语法稍微有区别,但原理相同)
1 2
| var websocket=new WebSocket("ws://echo.websocket.org/");
|
API
onopen/onclose/onmessage/onerror等,如下
2-1.open
建立连接,比如发送按钮事件,可以嵌套在open中,如果websocket没有连接,name发送按钮本身也没有意义
1 2 3
| websocket.onopen=function(){ consolet.log("websocket open") }
|
2-2.close
关闭连接
1 2 3
| websocket.onclose=function(){ consolet.log("websocket close") }
|
2-3.send
发送消息
1
| websocket.send("这是发送的消息")
|
2-4.message
接收消息
1 2 3
| websocket.onmessage=function(e){ consolet.log(e.data) }
|
对于message来说,e.data只是普通的字符串消息接收
但是因为实际的需求,如:用户离开/进入/统计等等
需要将消息分离,那么我们可以用对象的方式来操作信息
2-5.error
错误情况
1 2 3
| websocket.onerror=function(err){ consolet.log(err) }
|
3.格式化消息改造
通过以上的基础组件,我们可以实现简单的webSocket通信,但是稍微复杂一些的信息格式却难以完成,比如用户离开/进入/统计等
我们可以对消息进行JSON格式化来完成这样的基础实现
3-1.服务器改造
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42
| var ws = require("nodejs-websocket") var port = 8000; var clientCount = 0;
var server = ws.createServer(function (conn) { console.log("New connection");
clientCount++; conn.nickname = '用户' + clientCount;
var mes = {}; mes.type = "enter"; mes.data = conn.nickname + "进入房间"; broadcast(JSON.stringify(mes));
conn.on("text", function (str) { var mes = {}; mes.type = "message"; mes.data = conn.nickname + "说:" + str; broadcast(JSON.stringify(mes)) });
conn.on("close", function (code, reason) { var mes = {}; mes.type = "leave"; mes.data = conn.nickname + "离开房间"; broadcast(JSON.stringify(mes)); });
conn.on("error", function (err) { console.log(err) })
}).listen(port);
console.log("WebSocket Start Success:" + port);
function broadcast(msg) { server.connections.forEach(function (connection) { connection.sendText(msg); }) }
|
如上,将消息封装为一个mes对象,通过定义其属性来完成分类消息的发送
type="enter"
表示进入
type="leave"
表示离开
data
表示封装的消息
发送时将消息格式化为JSON字符串发送到前段即可
3-2.客户端改造
通过类型的判断,来实现想要的显示方式
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41
| <!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8"> <title>Websocket</title> </head> <body> <h1>WebSocket</h1> <input type="text" id="sendText" /> <button id="sendBtn">发送</button> <script> var webSocket=new WebSocket("ws://localhost:8000/"); var sendBtn = document.getElementById("sendBtn"); function showMessage(data,type){ var div= document.createElement(div); div.innerHTML="<br/>"+data; if (type=="enter"){ div.style.color="blue"; } if (type=="leave"){ div.style.color="red"; } document.body.appendChild(div); } webSocket.onopen=function () { sendBtn.onclick=function () { var sendText = document.getElementById("sendText").value; if (sendText){ webSocket.send(sendText); } } }; webSocket.onclose=function () { }; webSocket.onmessage=function (e) { var mes=JSON.parse(e.data); showMessage(mes.data,mes.type); } </script> </body> </html>
|
以上是原生的WebSocket,如果需要更为丰富的通信,可以使用Socket.IO框架来实现
4.Socket.IO框架
支持包括java/python/c++等多语言框架(底部连接)
NodeJs案例
通过以下指令安装socket.io模块
(需要nodejs环境和c编译器环境)
4-1.服务端
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22
| var server = require('http').createServer(); var io = require('socket.io')(server);
io.on('connection', function (socket) {
socket.on('Dony15',function (data) { console.log(data) socket.emit('Dony15',data); }) });
server.listen(3000, function () { console.log('listen on *:3000'); });
|
注意emit
当其为io中的函数socket.emit时,代表的是发送
当io.emit时,代表的是广播
4-2.客户端
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17
| <!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8"> <title>WebSocketIO</title> <script src="https://cdnjs.cloudflare.com/ajax/libs/socket.io/2.0.3/socket.io.js"></script> </head> <body> <script> var socket=io('ws://localhost:3000'); socket.on('Dony15',function (data) { console.log(data); }) socket.emit('Dony15',{name:'长贵',age:30}); </script> </body> </html>
|
4-3.Socket.IO服务端改造
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20
| var server = require('http').createServer(); var io=require('socket.io')(server);
var PORT = 3000; var clientCount = 0;
io.on('connection',function (socket) { clientCount++; socket.nickname = '用户' + clientCount; io.emit('enter',socket.nickname+'进入');
socket.on('message',function (str) { io.emit('message',socket.nickname+'说:'+str) });
socket.on('disconnect',function () { io.emit('leave',socket.nickname+'离开'); }); }); server.listen(PORT);
|
4-4.Socket.IO客户端改造
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48
| <!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8"> <title>WebSocketIO</title> <script src="https://cdnjs.cloudflare.com/ajax/libs/socket.io/2.0.3/socket.io.js"></script>//引入在线Socket.IO.js,开发建立离线使用 </head> <body> <h1>WebSocket</h1> <input type="text" id="sendText"/> <button id="sendBtn">发送</button> <script> var socket = io("ws://localhost:3000/"); var sendBtn = document.getElementById("sendBtn");
function showMessage(data, type) { var div = document.createElement(div); div.innerHTML = "<br/>" + data; if (type == "enter") { div.style.color = "blue"; } if (type == "leave") { div.style.color = "red"; } document.body.appendChild(div); } sendBtn.onclick = function () { var sendText = document.getElementById("sendText").value; if (sendText) { socket.emit('message', sendText); } };
socket.on('enter',function (data) { showMessage(data,'enter'); }); socket.on('leave',function (data) { showMessage(data,'leave'); }); socket.on('message',function (data) { showMessage(data,'message'); }) </script> </body> </html>
|
4-5.示例截图
5.传送门
慕课网WebSocket入门教程
https://www.imooc.com/learn/861
Socket.IO官网文档
https://socket.io/get-started/chat/
多语言GitHub服务器示例社区维护