这段时间学习了 socket.io, 用它写了小项目, 在此总结下它的基本使用方式和一些要点.
socket.io 是基于 Node.JS 和 webSocket 协议的实时通信开源框架, 它包括客户端的 JavaScript 和服务器端的 Node.JS.
服务端
这里后端使用的框架是 koa2,socket.io 将自身绑定到 koa 的进程到中去, 其中最重要的事件就是 connection 和 disconnect. 它们是框架本身定义的系统事件, 也就意味着它是自然就存在的不需要我们自定义, 当然还有其它系统事件, 但很少会用得到.
- const koa = require('koa')
- const App = new koa()
- const server = require('http').createServer(App.callback())
- const io = require('socket.io')(server)
- // 监听 connect 事件
- io.on('connection', socket => {
- socket.emit('open');// 通知客户端已连接
- console.log('connected');
- // 监听 disconnect 事件
- socket.on('disconnect', () => {
- console.log('disconnect')
- }
- });
- server.listen(3001);
客户端
Web 端直接传入 url 地址即可, 其中这里监听的 open 事件是用户自定义的, 对应服务端的则是发送 open 事件.
- import io from 'socket.io-client';
- // 建立 websocket 连接
- const socket = io('http://127.0.0.1:3001');
- // 收到 server 的连接确认
- socket.on('open', () => {
- showTip('socket io is open !');
- init();
- });
emit 和 on
emit 和 on 是最重要的两个 API, 分别对应 发送 和 监听 事件.
socket.emit(eventName[, ...args]): 发射 (触发) 一个事件
socket.on(eventName, callback): 监听一个 emit 发射的事件
我们可以非常自由的在服务端定义并发送一个事件 emit, 然后在客户端监听 on, 反过来也一样.
发送的内容格式也非常自由, 既可以是基本数据类型 Number,String,Boolean 等, 也可以是 Object,Array 类型, 甚至还可以是函数. 而用回调函数的方式则可以进行更便携的交互.
- /*** 服务端 **/
- socket.on('message',data =>{
- console.log(data)
- });
- socket.emit('send','hello everybody');
- /*** 客户端 **/
- socket.emit('message',{id:'1',txt:'hello'});
- socket.on('send',data =>{
- console.log(data);
- });
- // 回调函数
- /*** 服务端 **/
- socket.on('sayit', (Word, callback)=> {
- callback('say' + Word);
- });
- /*** 客户端 **/
- socket.emit('sayit', 'wow', data => {
- console.log(data); // say wow
- });
broadcast 广播
broadcast 默认是向所有的 socket 连接进行广播, 但是不包括发送者自身, 如果自己也打算接收消息的话, 需要给自己单独发送.
- /*** 服务端 **/
- io.on('connection', socket => {
- const data= {
- txt:'new user login',
- time:new Date()
- }
- // 广播向所有 socket 连接
- socket.broadcast.emit('userin',data);
- // 给自己也发一份
- socket.emit('userin',data);
- });
namespace 命名空间
如果你想隔离作用域, 或者划分业务模块, namespace 是个有效的法子. namespace 相当于建立新的频道, 你可以在一个 socket.io 服务上面隔离不同的连接, 事件和中间件.
默认的连接也是有 namespace 的, 那就是 /;
使用命名空间的方式一: 直接在链接后面加子域名, 这种其实用的还是同一个 sokcet 连接, 可以看成是软隔离吧.
- /*** 客户端 **/
- import io from 'socket.io-client';
- // 默认的 namespace
- const socket = io('http://127.0.0.1:3001');
- // mypath
- const socket = io('http://127.0.0.1:3001/mypath', {
- forceNew: true
- });
- /*** 服务端 **/
- // 默认的 namespace
- io.on('connection', socket => {
- });
- // mypath
- io.of('/mypath').on('connection', socket => {
- });
使用命名空间的方式二: path 参数, 这种就是实打实的重新起了一个 socket 服务了.
- /*** 客户端 **/
- const socket = io('http://localhost', {
- path: '/mypath'
- });
- /*** 服务端 **/
- // 另外重新起 socket 服务
- const io = require('socket.io')({
- path: '/mypath'
- });
middleware 中间件
socket.io 的中间件 和 kao2 的非常相似, 这意味着我们可以在变动很小的情况下, 将 koa2 的中间件改造为 socket.io 所用.
- const mypath = io.of('/mypath').on('connection', socket => {
- socket.on('message', data => {
- });
- });
- // 中间件
- const auth = (socket, next) => {
- const data = socket.request;
- if(!verify(data)){
- throw new Error('not verify');
- }
- next();
- }
- // mypath 这个 namespace 注册中间件
- mypath.use(auth);
- rooms
每一个 socket 连接都会有一个独一无二的标志, 那就是 socket.id, 我们就是通过 id 来区分不同连接的. 除此之外, socket.id 本身也是房间 room 的标志, 通俗讲, 每个 socket 连接自身都拥有一间房 room. 那么我们就可以给这个 room 发送消息, 还有如果你加入了房间, 就能接受到房间里的广播信息. 当然你可以自定义 room , 让 socket 连接加入或离开. 如果 socket 连接 disconnect 之后, 会自动离开 room.
而这就是实现 单独聊天 和 群组聊天 的基础, 来看一下对应的 API.
socket.join(rooms[, callback]): 加入房间
socket.leave(room[, callback]) : 离开房间
socket.to(room): 给房间发送消息
- // 自定义 room
- io.on('connection', socket =>{
- socket.join('some room')); // 加入房间
- socket.leave('some room'); // 离开房间
- });
- // 向房间里的所有客户端发送消息
- io.to('some room').emit('some event');
- // 默认房间(每一个 id 一个 room)
- socket.on('say to someone', (id, msg) => {
- socket.broadcast.to(id).emit('my message', msg);
- });
总结
相信有了以上介绍的基础知识, 再加上官网对应的文档, 要开发聊天室或者其他 实时通信 的项目, 是一件易如反掌的事情
socket.io 官网 https://socket.io/ 里面有对 API 非常详细的讲解和用例.
来源: https://www.cnblogs.com/edwardloveyou/p/10625152.html