socket.io——学习demo

socket.io 旨在不同版本的浏览器间实现实时通信,在多种传输方式中自动选择最有效方式。

通信,双工
发送事件:socket.emit ('eventName',{data})
响应事件:socket.on( 'enventName' ,{data} )

socket.io 服务端API总结:

//发送给所有的客户端包括自己
io.emit('hello', 'to all clients');
//发送给同一个房间的所有客户端包括自己
io.to('room42').emit('hello', "to all clients in 'room42' room");

io.on('connection', (socket) => {
  //只发送给自己 
 socket.emit("hello","only sender");
//发送给所有客户端不包括自己
  socket.broadcast.emit('hello', 'to all clients except sender');
//发送给同一个房间的所有客户端,不包括自己
  socket.to('room42').emit('hello', "to all clients in 'room42' room except sender");
});

在以上的学习基础之上,建立了一个小的demo,来对socket.io有个深刻的理解。

需求:实现一个多人协同编辑一段文本

服务器端采用nodejs+socket.io:

首先配置package.json

{
    "name": "socket2",
    "version": "1.0.0",
    "description": "socket io  demo",
    "main": "app.js",
    "scripts": {
        "start": "node app.js"
    },
    "author": "daisy",
    "license": "ISC",
    "devDependencies": {},
    "dependencies": {
        "socket.io": "^2.0.4",
        "socket.io-redis": "^5.2.0",
        "node-windows": "^0.1.14"
    }
}

执行命令安装相关的依赖:

npm install

接下来开始写服务端代码:建立一个js文件,名为app.js

const io = require('socket.io').listen(8124);
const redis = require('socket.io-redis');
const client = require('redis').createClient({ host: '192.168.103.52', port: 6379, detect_buffers: true });
const adapter = redis({ host: '192.168.103.52', port: 6379 });
const prefix = 'socket.io';
const namespace = 'mindLock';
adapter.pubClient.on('error', function () { });
adapter.subClient.on('error', function () { });
io.adapter(adapter);

function noop() { }
// 根据key获取redis信息
function getInfo(key, cb = noop) {
    client.get(key, (err, reply) => {
        let obj;
        if (!reply) obj = {};
        else obj = JSON.parse(reply.toString());
        cb(obj);
    });
}

io.on('connection', function (socket) {
    let room = socket.handshake.query.id;
    let userId = socket.handshake.query.userId;
    if (!room) return socket.disconnect();
    socket.join(room); // 加入房间
    let channel = prefix + '#' + namespace + '#' + room + '#'; // redis中存储名

    var value = getInfo(channel);
    //初始化状态
    socket.on("init", function () {
        getInfo(channel, (obj) => {
            if (!obj) { return; }
            if (obj.isLock && obj.userId != userId) {
                socket.emit("lock");
            }
            socket.emit("changeValue", { value: obj.inputValue });
        })
    });

    socket.on('newValue', function (data) {
        //发送内容,不包括自己
        socket.broadcast.to(room).emit("lock");
        socket.broadcast.to(room).emit("changeValue", { value: data.newValue });
        //将最新的数据存到数据库
        var obj = { inputValue: data.newValue, isLock: true, userId: userId };
        client.set(channel, JSON.stringify(obj));
    });

    socket.on('unlock', function () {
        //手动解锁,不包括自己
        socket.to(room).emit("manuallyUnlock");

        getInfo(channel, (obj) => {
            obj["isLock"] = false;
            client.set(channel, JSON.stringify(obj));
        })
    });

    socket.on('disconnect', () => {
        //断开连接,say goodbye ,包括自己
        io.to(room).emit('leave', userId + ":left");
        //如果是自己锁的,就解锁
        getInfo(channel, (obj) => {
            if (obj.userId == userId) {
                obj["isLock"] = false;
                socket.to(room).emit("manuallyUnlock");
                client.set(channel, JSON.stringify(obj));
            }
        })
        io.in(room).clients((err, clients) => {
            if (!clients.length) client.del(channel);
        });
    });
});

io.of('/').adapter.clients((err, clients) => {
    console.log(clients); // an array containing all connected socket ids
});

然后再编写客户端代码

新建一个html文件,名为index.html,

客户端使用vue+element-ui

代码如下:






    
    socket.io 测试
    
    
    
    
    
    




    

{{title}}

解锁

这样一切就准备就绪,然后启动服务器,使用命令 node app.js 。

demo展示结果

用两个浏览器打开index.html,可以看到如下的效果,同时只有一个人可以锁定编辑,锁定编辑的人可以解锁。一旦开始编辑,就上锁。编辑内容实时同步。

socket.io——学习demo_第1张图片

以上就是demo的全部代码,希望能够帮助大家学习socket.io的执行原理。

下一篇文章介绍如何将nodejs服务安装成windows服务,使得开机启动。

你可能感兴趣的:(socket.io)