简介
WebSocket 是 HTML5 开始提供的一种在单个 TCP 连接上进行全双工通讯的协议。
WebSocket 使得客户端和服务器之间的数据交换变得更加简单,允许服务端主动向客户端推送数据。在 WebSocket API 中,浏览器和服务器只需要完成一次握手,两者之间就直接可以创建持久性的连接,并进行双向数据传输。
在 WebSocket API 中,浏览器和服务器只需要做一个握手的动作,然后,浏览器和服务器之间就形成了一条快速通道。两者之间就直接可以数据互相传送。
现在,很多网站为了实现推送技术,所用的技术都是 Ajax 轮询。轮询是在特定的的时间间隔(如每1秒),由浏览器对服务器发出HTTP请求,然后由服务器返回最新的数据给客户端的浏览器。这种传统的模式带来很明显的缺点,即浏览器需要不断的向服务器发出请求,然而HTTP请求可能包含较长的头部,其中真正有效的数据可能只是很小的一部分,显然这样会浪费很多的带宽等资源。
HTML5 定义的 WebSocket 协议,能更好的节省服务器资源和带宽,并且能够更实时地进行通讯。
浏览器通过 JavaScript 向服务器发出建立 WebSocket 连接的请求,连接建立以后,客户端和服务器端就可以通过 TCP 连接直接交换数据。
当你获取 Web Socket 连接后,你可以通过 send() 方法来向服务器发送数据,并通过 onmessage 事件来接收服务器返回的数据。
例子
以下例子以node.js来搭建服务端。为了简单明了,服务端我们称为B端,客户端称为A端
B端编写
在项目的根目录下安装 nodejs-websocket (npm install nodejs-websocket),然后编写以下代码 :
const ws = require('nodejs-websocket');
let server = ws.createServer((conn)=>{
console.log('new connection');
}).listen(8083);
这样我们就建立了一个websocket的服务器了,监听的端口在8083。
A端编写
const ws = new WebSocket('ws://localhost:8083');
ws://localhost:8083是服务器的地址,需要注意的是WebSocket使用的是ws协议。
现在把服务器启动起来,在命令窗口下进入服务器的目录,输入node Server.js,如下 :
然后运行html页面,当用户链接成功后,后台会输出new connection,如下图 :
互相发送数据
建立了链接后,A端和B端都可以互相发送数据,这个操作由谁发起都可以。这是websocket和ajax的最大区别。
A端给B端发送数据
使用WebSocket的send方法,A端可以发送数据给B端。如 :
ws.onopen = function(){
ws.send('来自客户端的消息');
};
发送数据前,要确保websocket建立连接完成 。当websocket建立连接完成的时候,会触发一个钩子函数,onopen。所以需要写一个onopen事件。
websocket总共常用的有4种事件 :
onopen -------------- websocket建立连接完成时触发
onclose -------------- websocket连接被关闭或无法建立连接时触发
onmessage --------- websocket收到服务度发来的数据时触发
onerror --------------- websocket发生错误时触发
这时A端已经发送数据给B端了,但是B端还需要有一个函数,来接受A端发过来的消息。代码如下 :
conn.on('text', (str)=>{
console.log(str);
});
现在重新启动B端,然后在链接一次。如果无意外的话,会在dos窗口会打印出 “来自客户端的消息”
B端给A端发送数据
B端使用sendText方法可以给A端发送数据。
conn.sendText('来自服务端的消息'); //发送数据给客户端
同样的,A端也需要一个函数,来接受B端发过来的数据。上面已经介绍过了,使用的是onmessage钩子函数。
ws.onmessage = (e)=>{
console.log(e.data);
}
处理二次链接引起的错误
当有一个用户链接上服务器,如果这时在按刷新按钮,则服务器会崩掉。B端监听error事件则可以解决这个问题。如 :
conn.on('error', (error)=>{
//console.log(error);
});
广播消息
当B端接受到A端发送过来的数据,会把数据都转发给其它客户端,这叫做广播消息。代码如下 :
function boardcast(str){
//server.connections保存着每个链接进来的用户地址
server.connections.forEach((conn)=>{
conn.sendText(str);
});
}
在B端的onText事件调用改函数即可
关闭链接事件
conn.on('close', ()=>{
console.log('用户断开了链接');
});
完整代码以及案例下载
代码下载地址 :https://download.csdn.net/download/QQ408896436/12594892
代码
服务端
const ws = require('nodejs-websocket');
let server = ws.createServer((conn)=>{
console.log('new connection');
//接受客户端发来的消息
conn.on('text', (str)=>{
console.log(str);
//conn.sendText('来自服务端的消息'); //发送消息给客户端
boardcast(str); //广播
});
//处理用户关掉链接时的错误
conn.on('error', (error)=>{
//console.log(error);
});
//断开链接触发
conn.on('close', ()=>{
console.log('用户断开了链接');
});
}).listen(8083);
function boardcast(str){
//server.connections保存着每个链接进来的用户
server.connections.forEach((conn)=>{
conn.sendText(str);
});
}
console.log('server is runing...');
客户端
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>websocket demo</title>
</head>
<body>
<script>
const ws = new WebSocket('ws://localhost:8083');
//发送数据给服务端
ws.onopen = function(){
ws.send('来自客户端的消息');
};
//接受服务端发过来的消息
ws.onmessage = (e)=>{
console.log(e.data);
}
ws.onclose = (e)=>{
if(e.type === 'close'){
alert('无法建立连接或者服务器已关闭!');
}
}
//websocket发生错误
ws.onerror = (e)=>{
console.log(e);
}
</script>
</body>
</html>