• 使用 Socket.IO 开发聊天室


    前言

    Socket.IO 是一个用来实现实时双向通信的框架,其本质是基于 WebSocket 技术。

    我们首先来聊聊 WebSocket 技术,先设想这么一个场景:

    · 用户小A,打开了某个网站的充值界面,该界面上有一个付款的二维码。

    · 当小A 用某宝的 APP 扫码付款之后,网页要自动跳转到付款成功的界面。最简单的方法就是网页每隔一段时间就请求一次服务器——“怎么样?那货付款没有?”,“怎么样?还没付吗?”,“怎么样?这次总该付了吧”。

    · 当接收到服务端返回确认付款的标识后,页面再进行跳转。

    这种定时对服务端发送 HTTP 请求的技术也被称为“轮询”。轮询的缺点也显而易见,短时间内的多次访问无疑会对服务器造成很大压力。

      后来,人们发明了长轮询技术。这与短轮询的区别在于,每次浏览器请求服务器后,服务器并不会立即返回“用户还未付款”的结果,而是一直将 HTTP 保持在挂起状态,只有当用户付款后才会返回给浏览器 “用户已经付款” 的结果。当然,如果用户在规定时间内仍未付款还是会断开此次连接,之后浏览器再开始发送下一轮的长连接。相比短轮询,长轮询有了一定的优势,但这还是不够好。直到 HTML5 里 WebSocket 技术的诞生。

      WebSocket,即 Web 浏览器与 Web 服务器之间的全双工通信标准。最初 WebSocket 只是作为 HTML5 标准的一部分,而后来却逐渐变成了独立的协议标准。一旦浏览器与服务器建立起 WebSocket 协议的通信连接,之后所有的通信都依靠该协议进行。不论是服务器还是浏览器,任何一方都能向对方发送报文。通信过程中可相互发送 JSON、HTML或图片等任意格式的数据。

       关于 WebSocket 的原生 API 如何使用,本文不赘述了。 这里主要聊聊关于 Socket.IO 这个库的使用方式。Socket.IO 与 ws 等其他基于 WebSocket 通信的库相比,它的好处在于,当浏览器支持 WebSocket 技术时它能正常使用 WebSocket 来工作,当浏览器不支持 WebSocket 时,它能平稳退化成轮询进行工作。

    首先放出自己做的聊天室 DEMO 源码将源码克隆到本地,执行下面两个命令:

    npm install
    npm start

     接着用浏览器访问 localhost:8000 即可,实际界面如下图:

         

    Socket.IO 在客户端与服务端二者均有一套 API,我们举几个常用的进行说明。

    服务端

    new Server

    因为 WebSocket 协议是建立在 HTTP 协议之上的,所以在创建 WebSocket 服务时需要调用 http 模块并调用其下的 createServer 方法,将生成的 server 作为参数传入 socket.io 的方法中。

    var server = require('http').createServer(),
        io = require('socket.io')(server);
    
    server.listen(8000);

    io.onconnection(socket)

    io 的 connection 事件表示客户端与服务器成功建立连接,它会接收一个回调函数,该回调函数会接收一个 socket 参数。

    io.on('connection', (socket) => {
        console.log(socket);
    });

    io.emit(EventName, param1, param2...)

    io.emit 方法用于向服务器发送消息,其第一个参数表示自定义的数据名,后面表示需要配合事件传入的参数。

    io.on('connection', (socket) => {
        io.emit('server message', {msg: 'Hello World.'})
    });

    socket.on(EventName, callback)

    socket.on 方法用于接收客户端发送来的消息,EventName 参数为客户端自定义的事件名,callback 为回调函数,回调函数接收的参数即客户端传递来的参数。

    io.on('connection', (socket) => {
        socket.on('client message', (data) => {
            console.log(data);
        });
    });

    socket.broadcast.emit() 

    socket.broadcast.emit() 方法表示向除了自己以外的客户端发送消息。举个例子,当我们输入 “Message” 点击发送,只需要将 “Message” 通过服务器发送给其他客户端用于显示,而本地只需要将 “Message” 通过 js 代码添加进聊天窗口即可,而不需要经过服务器。

    io.on('connection', (socket) => {
        socket.broadcast.emit('server message', {
            msg: 'Hello World.'
        });
    });

    socket.ondisconnect

    socket 的 disconnect 事件表示客户端与服务端断开连接。

    io.on('connection', (socket) => {
        socket.on('disconnect', () => {
            console.log('连接已断开...');
        });
    });

    客户端

    首先需要引入 socket.io 模块中的 socket.io.js 文件。

    <!Doctype HTML>
    <html>
    <head>
        <title>Socket.IO chat</title>
        <script src="/socket.io/socket.io.js"></script>
    </head>
    </html>

    引入成功后,就可能通过 io() 生成客户端所用的 socket 对象。

    var socket = io();

    socket.emit(EventName, param1, param2, .....)

    socket.emit 方法用于客户端向服务端发送消息,服务端与之对应的是 socket.on 方法来接收消息。

    //客户端
    var socket = io();
    socket.emit('client message', {
        msg: 'Hello Server'
    });
    
    //服务端
    io.on('connection', (socket) => {
        socket.on('client message', (data) => {
            console.log(data.msg); // Hello Server
        });
    });

    socket.on(EventName)

    socket.on 方法用于接收服务端发来的消息

    //服务端
    io.on('connection', (socket) => {
        io.emit('server message', {
            msg: 'Hello Client'
        });
    });
    
    //客户端
    var socket = io();
    socket.on('server message', (data) => {
        console.log(data.msg); // Hello Client
    });

    介绍完 Socket.IO 的 API,下面开始尝试写聊天室的 DEMO。

    首先创建目录如下:

    其中 server.js 中保存着服务端的代码,client 文件夹中保存着客户端代码,包括 HTML、CSS、JS、图片等。

    编写 server.js 如下:

    var express = require('express'),
        app = express(),
        server = require('http').createServer(app),
        io = require('socket.io')(server),
        port = process.env.PORT || 8000;
    
    //通过 express 加载前端部分的静态资源文件 app.use(express.static(__dirname
    + '/client')); io.on('connection', (socket) => {
       //通过 socket.id 创建简易的用户名 let user = '游客' + socket.id.substring(0, 6); //通知用户进入 io.local.emit('user conncet', user + '进入聊天室'); //接收从客户端发送来的消息,拼上消息发布者的名字后,广播给其他客户端 socket.on('client message', (data) => { data.author = user; //将消息广播给除自己以外的客户端 socket.broadcast.emit('server message', data); }); //通知用户离开 socket.on('disconnect', () => { io.local.emit('user disconnect', user + '离开聊天室'); }); }); server.listen(port, () => { console.log('listening on %d...', port); });

    前端部分代码省略,这里只简单写一个发送消息的方法,具体的代码请参考 DEMO 源码

    var socket = io();
    
    function sendMsg() {
        var message = document.querySelector('#input');
        
        socket.emit('client message', {
            text: message,
            time: new Date()
        });
    
        document.querySelector('#content').innerHTML += '<div class="msgList">'+message+'</div>';
    }

    如上,当运行 server.js 文件后,在浏览器地址栏中输入 localhost:8000 就可以看到聊天室的界面了。 这样我们就完成了一个简易的聊天室,它包括如下功能:

    · 发送/接收消息

    · 通知用户进入/离开

    · 为进入聊天室的用户命名,名称唯一

    有兴趣的朋友还可以尝试自行完成如下功能:

    · 用户登陆

    · 查看所有在线用户

    · @ 功能

    ···

    感觉你的浏览,希望能有所帮助。

  • 相关阅读:
    boxShadow通用css效果
    electron安装+运行+打包成桌面应用+打包成安装文件+开机自启动
    electron-vue项目创建失败
    dpr——设备像素比(device pixel ratio)
    electron与vue集成
    一文让你理解vue history和hash模式实现
    vue router生命周期说明
    Vue keep-alive实践总结
    Vuejs路由过度动画
    ReactJS 的5种路由模式
  • 原文地址:https://www.cnblogs.com/ghost-xyx/p/7060070.html
Copyright © 2020-2023  润新知