连续复制
一键复制
一键打包
Socket.io是什么
Socket.io是一个用于在浏览器和服务器之间进行实时,双向和基于事件的通信库。
Socket.io包装了websocket,在浏览器支持的情况下优先使用websocket进行连接,否则回退到HTTP长轮询的方式,解决了部分浏览器暂不支持websocket的问题。
安装方法
在node.js服务端使用时,通过npm安装
npm install socket.io
在浏览器中使用时可通过两种方式
第一种
// socket.io在服务端的程序会自动将客户端的文件在该路径下暴露出来,
// 因此直接通过src标签引入即可
<script src="/socket.io/socket.io.js"></script>
第二种
// 在服务端...
// 如果不想通过服务端暴露的文件引用,则可以禁用该功能
const io = require('socket.io')({
// 不启用
serveClient: false
});
// 在客户端
// 然后通过cdn等方式引入(减轻自己服务器的压力)
<script src="https://cdnjs.cloudflare.com/ajax/libs/socket.io/2.3.0/socket.io.js"></script>
与Express一起使用
const app = require('express')();
const server = require('http').createServer(app);
const options = { /* ... */ };
const io = require('socket.io')(server, options);
io.on('connection', socket => { /* ... */ });
server.listen(3000);
基本概念
命名空间(namespace)
命令空间是一个通信的通道,它便于分割应用的逻辑
例如:将所有客户端分割成两个空间,一个是Default空间,一个是Admin空间。对于Default空间我们可以做一些通用的操作,而对于Admin空间,我们用于做一些专用的操作。
// 在服务端...
// 建立admin命名空间
const adminNamespace = io.of('/admin');
// 对admin命名空间中的所有socket使用该中间件
adminNamespace.use((socket, next) => {
// 例如做一些验证操作
// ensure the user has sufficient rights
next();
});
// 监听admin命名空间中所有客户端的connection事件
adminNamespace.on('connection', socket => {
...
});
// 在客户端...
// 连接admin命名空间
const socket = io('/admin');
// 监听connection事件
socket.on('connection', socket => {
...
});
默认命名空间
默认命名空间
/
, 所有的客户端都会默认的连接到这个命名空间
房间(room)
在每个命名空间内,可以定义任意的通道,称为“ Room”,套接字可以加入和退出
// 在服务端...
io.on('connection', socket => {
// 客户端建立连接之后,将其加入房间
socket.join('some room');
// 使用同样的方式离开一个房间
socket.leave('some room')
});
默认房间
每一个socket都有一个随机分配的标识符
Socket#id
,每一个socket都会自动加入以其ID标识的房间
使用中间件
// 为默认命名空间注册一个中间件
io.use((socket, next) => {
if (isValid(socket.request)) {
next();
} else {
next(new Error('invalid'));
}
});
// 为自定义的命名空间制定一个中间件
io.of('/admin').use(async (socket, next) => {
const user = await fetchUser(socket.handshake.query);
if (user.isAdmin) {
socket.user = user;
next();
} else {
next(new Error('forbidden'));
}
});
================================================
// 可以为一个命名空间注册多个中间件,他们会依次执行
io.use((socket, next) => {
next();
});
io.use((socket, next) => {
next(new Error('thou shall not pass'));
});
io.use((socket, next) => {
// 不会执行,因为前一个中间件返回了错误
next();
});
// 如果next方法返回了Error,那么客户端会收到error事件
====================================================
// 使用express中间件
// 大多数express的中间件都需要与socket.io兼容,你只需要将这些中间件,用一个函数包起来
const wrap = middleware => (socket, next) => middleware(socket.request, {}, next);
const session = require('express-session');
io.use(wrap(session({ secret: 'cats' })));
io.on('connect', (socket) => {
const session = socket.request.session;
});
发送消息
现在已经知道了命名空间和房间,然后就该往这些命名空间和房间发送消息了
// 在服务端...
// 监听连接事件
io.on('connect', onConnect);
// 连接成功后使用的函数
function onConnect(socket){
// 发送到这个刚刚连接成功的客户端
socket.emit('hello', 'can you hear me?', 1, 2, 'abc');
// 发送给所有客户端,不包括发送者
socket.broadcast.emit('broadcast', 'hello friends!');
// 发送到所有在game房间的客户端,不包括发送者
socket.to('game').emit('nice game', "let's play a game");
// 发送到所有在game1或game2的客户端,不包括发送者
socket.to('game1').to('game2').emit('nice game', "let's play a game (too)");
// 发送到所有的客户端,包括发送者
io.in('game').emit('big-announcement', 'the game will start soon');
// 发送到所有在myNamespace命名空间的客户端,包括发送者
io.of('myNamespace').emit('bigger-announcement', 'the tournament will start soon');
// 发送到在myNamespace命名空间中的room房间中的客户端,包括发送者
io.of('myNamespace').to('room').emit('event', 'message');
// 发送到指定socketId的客户端(私聊)
io.to(socketId).emit('hey', 'I just met you');
// 注意: `socket.to(socket.id).emit()` 不会如预期那样,
// 发送消息给指定socket, 而是会把socket.id当作room的名称
// 将消息发给名为socket.id的room的房间中的每个socket(除开发送者)
// 发送消息,并且带有确认回调
socket.emit('question', 'do you think so?', function (answer) {});
// 发送消息,但不使用压缩
socket.compress(false).emit('uncompressed', "that's rough");
// sending a message that might be dropped if the client is not ready to receive messages
// 发送一条不可靠消息,该消息可能由于客户端未准备好而丢失
socket.volatile.emit('maybe', 'do you really need it?');
// 指定要发送的数据是否具有二进制数据
socket.binary(false).emit('what', 'I have no binaries!');
// 发送到node上的所有客户端(使用多个node时)
io.local.emit('hi', 'my lovely babies');
// 发送到所有客户端
io.emit('an event sent to all connected clients');
};
评论已关闭