Socket.IO + Node.js实现双工通信
基础知识介绍
WebSocket实现了B/S的全双工通信,其基本思想是保持连接持久打开
Socket.IO是Node.js的一个模块,提供WebSocket通信方式(对于不兼容的系统,使用Ajax长轮询等备选方案)
WebSocket不支持注入重新连接处理,心跳检测等功能,但Socket.IO库提供了这些特性,且解决了跨域问题。
Socket.IO侦听用户连接和断开连接
从零开始,步骤如下:
-
服务器端,引入Socket.IO库,并将其套在服务器(server)上:
var server = http.createServer(function (req,res) { fs.readFile('./index.html',function(error,data) { res.writeHead(200,{ 'Content-Type': 'text/html' }); res.end(data,'utf-8'); }); }).listen(80,"127.0.0.1"); var io = require('socket.io').listen(server);
-
服务器端,打开connection和disconnect监听
// 监听客户端连接事件 io.sockets.on('connection',function (socket) { console.log('User connected'); // 监听离线事件 socket.on('disconnect',function () { console.log('User disconnected'); }); });
-
客户端,引入Socket.IO的客户端js库,并连接到指定服务器
//引入Socket.IO
至此,每当有客户端连接或断开连接到服务器的时候,服务器都能够感知(利用这个可做实时在线人数统计)
Socket.IO实现服务器和单一客户端双向通信
基于上条功能,服务器和客户端的通信步骤如下:
-
服务器向客户端发送事件
-
客户端向服务器发送事件(和上面一模一样)
-
服务器端的广播通信,客户端无权
使用socket.broadcast.emit(事件名,数据);即可实现! 只要注册过该‘事件名’的客户端,都会收到消息
Socket.IO实现客户端之间通信(利用服务器的广播通信)
下图给出了客户端之间通信的必要过程
代码汇总
服务器端:
var http = require('http'),fs = require('fs');
// 创建服务
var server = http.createServer(function (req,res) {
fs.readFile('./index.html',data) {
res.writeHead(200,{ 'Content-Type': 'text/html' });
res.end(data,'utf-8');
});
}).listen(80,"127.0.0.1");
console.log('Server running at http://127.0.0.1:3000/');
// 创建socket服务,附加在server上
var io = require('socket.io').listen(server);
// 初始化网站在线人数
var counter = 0;
// 监听客户端连接事件
io.sockets.on('connection',function (socket) {
// 使在线人数加1
counter++;
// 在服务器端<a href="https://www.jb51.cc/tag/shuchu/" target="_blank" class="keywords">输出</a>消息
console.log('User connected');
// 给新连接的<a href="https://www.jb51.cc/tag/yonghu/" target="_blank" class="keywords">用户</a>发送“已连接”<a href="https://www.jb51.cc/tag/tishi/" target="_blank" class="keywords">提示</a>
socket.emit('message',{ text: 'You have connected!'});
// 广播通信:给其他<a href="https://www.jb51.cc/tag/yonghu/" target="_blank" class="keywords">用户</a>发送新的在线人<a href="https://www.jb51.cc/tag/shuliang/" target="_blank" class="keywords">数量</a>
socket.broadcast.emit('users',{ number: counter});
// 还要给新进来的<a href="https://www.jb51.cc/tag/yonghu/" target="_blank" class="keywords">用户</a>单独发送一个在线人<a href="https://www.jb51.cc/tag/shuliang/" target="_blank" class="keywords">数量</a>,因为广播消息并不会发给这个<a href="https://www.jb51.cc/tag/xinyonghu/" target="_blank" class="keywords">新用户</a>
socket.emit('users',{ number: counter});
// 监听离线事件
socket.on('disconnect',function () {
counet--;
console.log('User disconnected');
});
// 监听客户端发送聊天消息事件,并广播给所有客户端
socket.on('chat',function(data){
socket.broadcast.emit('getChat',data);
socket.emit('getyourChat',data);
})
});</code></pre>
客户端