node.js中使用socket.io + express进行实时消息推送
socket.io是一个websocket库,包含客户端的js和服务端的node.js,可以在不同浏览器和移动设备上构建实时应用。
一、安装 socket.io
npm install socket.io
二、通过socket.io创建一个简单应用
const http = require('http');
const path = require('path');
const express = require('express'); //创建一个应用,注意app其实就是一个函数,类似function(req, res) {}
let app = express();
//创建一个http服务器,既然app是一个函数,那这里就可以传入。
let server = http.createServer(app);
//注意,websocket的握手是需要依赖http服务的,所以这里要把server传入进去。
let io = require('socket.io')(server); app.get('/', function (req, res) {
res.sendFile(path.join(__dirname, 'index.html'));
}); //有新的客户端连接时触发
io.on('connection', function (socket) {
//接收到消息时触发
socket.on('message', function (data) {
console.log('服务端收到 : ', data);
//注意send()方法其实是发送一个 'message' 事件
//客户端要通过on('message')来响应
socket.send('你好客户端, ' + data);
});
//发生错误时触发
socket.on('error', function (err) {
console.log(err);
});
}); server.listen(8888);
index.html的代码:
<!DOCTYPE html>
<html lang="zh-CN">
<head>
<meta charset="UTF-8">
<title>Title</title>
</head>
<body>
<input type="text" id="msg">
<input type="button" id="send" value="发送">
<ul id="receive"></ul> <!-- /socket.io/socket.io.js 这个引用路径是固定的,socket.io会自动帮我们解析 -->
<script src="/socket.io/socket.io.js"></script>
<script>
var socket = io.connect('http://localhost:8888'); //连接成功时触发
socket.on('connect', function () {
console.log('连接成功');
}); //连接断开时触发
socket.on('disconnect', function () {
console.log('连接断开');
}); //收到消息时触发
socket.on('message', function (data) {
var node = document.createElement("li");
node.innerHTML = "客户端收到 : " + data;
document.querySelector("#receive").appendChild(node);
}); document.querySelector("#send").onclick = function () {
var msg = document.querySelector("#msg").value;
socket.send(msg);
};
</script>
</body>
</html>
这样我们就可以在客户端建立与服务端的实时消息传送。注意 send() 方法只是 emit 方法的封装,等同于 emit('message', args)。
我们通过 emit 方法可以自定义的发送事件,并监听事件。
const http = require('http');
const path = require('path');
let app = require('express')();
let server = http.createServer(app);
let io = require('socket.io')(server); app.get('/', function (req, res) {
res.sendFile(path.join(__dirname, 'index.html'));
}); io.on('connection', function (socket) {
socket.on('message', function (data) {
console.log('服务端收到 : ', data);
socket.send('你好客户端, ' + data);
}); //监听自定义事件
socket.on('myevent', function (data) {
console.log('客户端发送了一个自定义事件', data);
});
}); server.listen(8888);
index.html的代码:
<!DOCTYPE html>
<html lang="zh-CN">
<head>
<meta charset="UTF-8">
<title>Title</title>
</head>
<body>
<input type="text" id="msg">
<input type="button" id="send" value="发送">
<input type="button" id="event" value="发送自定义事件">
<ul id="receive"></ul> <!-- /socket.io/socket.io.js 这个引用路径是固定的,socket.io会自动帮我们解析 -->
<script src="/socket.io/socket.io.js"></script>
<script>
var socket = io.connect('http://localhost:8888'); //连接成功时触发
socket.on('connect', function () {
console.log('连接成功');
}); //连接断开时触发
socket.on('disconnect', function () {
console.log('连接断开');
}); //收到消息时触发
socket.on('message', function (data) {
var node = document.createElement("li");
node.innerHTML = "客户端收到 : " + data;
document.querySelector("#receive").appendChild(node);
}); document.querySelector("#send").onclick = function () {
var msg = document.querySelector("#msg").value;
socket.send(msg);
}; document.querySelector("#event").onclick = function () {
var msg = document.querySelector("#msg").value;
//参数一表示,事件的名称
//参数二表示,要发送的数据
socket.emit("myevent", msg);
};
</script>
</body>
</html>
emit() 或 send() 还有第三个参数,用来设置消息发送成功后的回执。
const http = require('http');
const path = require('path');
const express = require('express');
let app = express();
let server = http.createServer(app);
let io = require('socket.io')(server); app.use(express.static(path.join(__dirname))); app.get('/', function (req, res) {
res.sendFile(path.join(__dirname, 'index.html'));
}); io.on('connection', function (socket) {
socket.on('message', function (data, callback) { socket.send('服务器发送 : ' + data, function (data) {
console.log(data);
}); //这里callback传入的参数会传递到客户端的send()回调函数里
callback('服务端的回执');
});
}); server.listen(8888);
index.html的代码:
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Title</title>
</head>
<body>
<input type="text" id="msg">
<input type="button" id="send" value="发送">
<script src="/socket.io/socket.io.js"></script>
<script>
var socket = io.connect('http://localhost:8888');
socket.on('connect', function () {
console.log('连接成功');
});
socket.on('message', function (data, callback) {
console.log('客户端收到 : ', data); //这里callback传入的值会传递到服务端的send()回调函数里
callback('客户端的回执');
});
document.querySelector("#send").onclick = function () {
var msg = document.querySelector("#msg").value;
socket.send(msg, function (data) {
console.log(data);
});
};
</script>
</body>
</html>
三、socket.io命名空间的概念
有些时候我们需要按不同的模块或功能去传递不同的消息,比如在 /user 模块下推送用户信息,在 /order 模块下推送订单信息,两者间互不干扰。
这个时候就需要用到命名空间了,socket.io把不同命名空间下的消息和事件分隔开了。
const http = require('http');
const path = require('path');
const express = require('express');
let app = express();
let server = http.createServer(app);
let io = require('socket.io')(server); app.use(express.static(path.join(__dirname))); app.get('/', function (req, res) {
res.sendFile(path.join(__dirname, 'index.html'));
}); //通过of()设置命名空间
//注意,如果没加of(),则默认使用'/'命名空间
io.of('/user').on('connection', function (socket) {
socket.on('message', function (data) {
console.log('/user : ', data);
//注意send()只会发送给当前客户端
//如果要进行群发
//用 io.of(命名空间).send() 发送命名空间下所有客户端,包括发送者。
//或者 socket.broadcast.send() 发送命名空间下所有客户端,不包括发送者。
//io.of('/user').send('服务端发送 : ' + data);
socket.broadcast.send('服务端发送 : ' + data);
});
}); io.of('/order').on('connection', function (socket) {
socket.on('message', function (data) {
console.log('/order : ', data);
socket.broadcast.send('服务端发送 : ' + data);
});
}); server.listen(8888);
user.html的代码:
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Title</title>
</head>
<body>
<input type="text" id="msg">
<input type="button" id="send" value="发送">
<script src="/socket.io/socket.io.js"></script>
<script>
var socket = io.connect('http://localhost:8888/user');
socket.on('connect', function () {
console.log('连接成功');
});
socket.on('message', function (data) {
console.log('客户端收到 : ', data);
});
document.querySelector("#send").onclick = function () {
var msg = document.querySelector("#msg").value;
//注意客户端的send()会发送到当前的socket命名空间下
socket.send(msg);
};
</script>
</body>
</html>
order.html的代码:
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Title</title>
</head>
<body>
<input type="text" id="msg">
<input type="button" id="send" value="发送">
<script src="/socket.io/socket.io.js"></script>
<script>
var socket = io.connect('http://localhost:8888/order');
socket.on('connect', function () {
console.log('连接成功');
});
socket.on('message', function (data) {
console.log('客户端收到 : ', data);
});
document.querySelector("#send").onclick = function () {
var msg = document.querySelector("#msg").value;
//注意客户端的send()会发送到当前的socket命名空间下
//socket.send(msg);
socket.send(msg);
};
</script>
</body>
</html>
/user 和 /order 不同命名空间下的消息彼此之间无法看到。
四、socket.io房间的概念
房间是一个命名空间下划分的,一个客户端可以进入多个房间。
如果在命名空间下进行广播,那该命名空间下的所有客户端和房间内的客户端都会收到消息。
如果在房间内进行广播,则该房间下的所有客户端会收到消息,房间外的不会影响。
const http = require('http');
const path = require('path');
const express = require('express');
let app = express();
let server = http.createServer(app);
let io = require('socket.io')(server); app.use(express.static(path.join(__dirname))); app.get('/', function (req, res) {
res.sendFile(path.join(__dirname, 'index.html'));
}); io.of('/user').on('connection', function (socket) {
let rooms = [];
//加入房间
socket.on('join', function (name) {
socket.join(name, function () {
if (!rooms.includes(name)) {
rooms.unshift(name);
}
console.log(`${socket.id} 加入房间 ${name}`);
console.log(rooms);
});
});
//离开房间
socket.on('leave', function (name) {
socket.leave(name, function () {
rooms = rooms.filter(function (value) {
return value !== name;
});
console.log(`${socket.id} 离开房间 ${name}`);
console.log(rooms);
});
});
//房间内的广播
socket.on('room_broadcast', function (data) {
//socket.to(rooms[0]).send('房间 ${rooms[0]} 内的广播 : ' + data); 房间下的所有客户端,不包括发送者
//io.of(命名空间).in(rooms[0]).send(`房间 ${rooms[0]} 内的广播 : ${data}`); 房间下的所有客户端,包括发送者
io.of('/user').in(rooms[0]).send(`房间 ${rooms[0]} 内的广播 : ${data}`);
});
//命名空间下的广播
socket.on('namespace_broadcast', function (data) {
//socket.broadcast.send('命名空间下的广播 : ' + data); 命名空间下所有客户端,不包括发送者
//io.of(命名空间).send('命名空间下的广播 : ' + data); 命名空间下所有客户端,包括发送者
io.of('/user').send('命名空间下的广播 : ' + data);
});
}); io.of('/order').on('connection', function (socket) {
socket.on('message', function (data) {
io.of('/order').send('命名空间下的广播 : ' + data);
});
}); server.listen(8888);
user.html的代码:
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Title</title>
</head>
<body>
<input type="text" id="msg">
<input type="button" id="room_send" value="房间内的广播">
<input type="button" id="namespace_send" value="命名空间下的广播">
<input type="button" class="join" room="001" value="加入房间001">
<input type="button" class="join" room="002" value="加入房间002">
<input type="button" class="leave" room="001" value="离开房间001">
<input type="button" class="leave" room="002" value="离开房间002">
<script src="/socket.io/socket.io.js"></script>
<script>
var socket = io.connect('http://localhost:8888/user');
socket.on('connect', function () {
console.log('连接成功');
});
socket.on('message', function (data) {
console.log('客户端收到 : ', data);
});
document.querySelector("#room_send").onclick = function () {
var msg = document.querySelector("#msg").value;
socket.emit("room_broadcast", msg);
};
document.querySelector("#namespace_send").onclick = function () {
var msg = document.querySelector("#msg").value;
socket.emit("namespace_broadcast", msg);
};
var joins = document.querySelectorAll(".join");
for (var ix = 0; ix < joins.length; ix++) {
joins[ix].onclick = function () {
socket.emit('join', this.getAttribute("room"));
};
}
var leaves = document.querySelectorAll(".leave");
for (var ix = 0; ix < leaves.length; ix++) {
leaves[ix].onclick = function () {
socket.emit('leave', this.getAttribute("room"));
};
}
</script>
</body>
</html>
通过 join() 和 leave() 加入房间或离开房间。通过 to() 方法指定向哪个房间发送消息。要发送多个房间,可以调用多次 to()。
node.js中使用socket.io + express进行实时消息推送的更多相关文章
- Socket.io+Notification实现浏览器消息推送
前言 socket.io: 包含对websocket的封装,可实现服务端和客户端之前的通信.详情见官网(虽然是英文文档,但还是通俗易懂).Notification: Html5新特性,用于浏览器的桌面 ...
- 基于socket.io的实时消息推送
用户访问Web站点的过程是基于HTTP协议的,而HTTP协议的工作模式是:请求-响应,客户端发出访问请求,服务器端以资源数据响应请求. 也就是说,服务器端始终是被动的,即使服务器端的资源数据发生变化, ...
- 【js学习】js连接RabbitMQ达到实时消息推送
js连接RabbitMQ达到实时消息推送 最近在自己捯饬一个网站,有一个功能是需要后端处理完数据把数据发布到MQ中,前端再从MQ中接收数据.但是前端连接MQ又成了一个问题,在网上搜了下资料,点进去一篇 ...
- ZH奶酪:基于ionic.io平台的ionic消息推送功能实现
Hybrid App越来越火,Ionic的框架也逐渐被更多的人熟知. 在mobile app中,消息推送是很必要的一个功能. 国内很多ionic应用的推送都是用的极光推送,最近研究了一下Ionic自己 ...
- Worktile中百万级实时消息推送服务的实现
Worktile中百万级实时消息推送服务的实现 出自:http://blog.jobbole.com/81125/
- [Node.js] Level 6. Socket.io
6.2 Setting Up socket.io Server-Side So far we've created an Express server. Now we want to start bu ...
- 【springboot】【socket】spring boot整合socket,实现服务器端两种消息推送
参考地址:https://www.cnblogs.com/hhhshct/p/8849449.html
- 使用Node.js的socket.io模块开发实时web程序
首发:个人博客,更新&纠错&回复 今天的思维漫游如下:从.net的windows程序开发,摸到nodejs的桌面程序开发,又熟悉了一下nodejs,对“异步”的理解有了上上周对操作系统 ...
- 使用Node.js+Socket.IO搭建WebSocket实时应用
Web领域的实时推送技术,也被称作Realtime技术.这种技术要达到的目的是让用户不需要刷新浏览器就可以获得实时更新.它有着广泛的应用场景,比如在线聊天室.在线客服系统.评论系统.WebIM等. W ...
随机推荐
- C# 左右补零
//不够4位补零 public static string addZero(int val) { string str = val + ""; int strLen = str.L ...
- 2.5 Visio2007不规则图形填充
1.确保线和线接口的地方正好相交,没有多出来的线: 2.将图形选中>组合: 3.选中图形>形状>操作>连接>填充颜色. 因为图形式几条线段拼合的,不是封闭图形,所以需要将 ...
- 量化分析v1
量化分析v1 # -*- coding: utf-8 -*- """ Created on Wed Apr 11 10:13:32 2018 @author: chens ...
- django 获取用户提交的数据 文件 表单
templates: <div> <form action="/detail" method="post" enctype="mul ...
- Windows Azure Virtual Network (13) 跨数据中心之间的虚拟网络点对点连接VNet Peering
<Windows Azure Platform 系列文章目录> 今天是大年初二,首先祝大家新年快乐,万事如意. 在笔者之前的文章中:Windows Azure Virtual Networ ...
- Python第一天:python2.x和python3.x的区别
查看Python版本 # python -V Python2.7.5是centos7中默认安装的Python [root@localhost ~]# python -V Python [root@lo ...
- 20165312 2017-2018-2《Java程序设计》课程总结
20165312 2017-2018-2<Java程序设计>课程总结 每周作业链接汇总 预备作业1:我期望的师生关系 预备作业2:C语言基础调查和java学习展望 预备作业3:Linux安 ...
- 一些恶作剧的vbs程序代码
恶作剧的vbs代码,这里提供的都是一些死循环或导致系统死机的vbs对机器没坏处,最多关机重启一下就可以了,将下面的任意一段代码保存为*.vbs即可 循环弹窗: do msgbox "hi&q ...
- Chrome 插件安装技巧
参考http://blog.csdn.net/shiyaru1314/article/details/49303317 最近在学习WEBAPI 由于没有界面可以调试,需要安装Chrome中的插件 P ...
- 安装系统,用cmd进行分区
步骤1:在“您想将Windows安装在何处”的界面按住“Shift+F10”,调出命令行窗口,输入diskpart并点击回车 步骤2: 输入list disk点击回车,列出所有磁盘磁盘是从0开始排序的 ...