socket.io入门,简易聊天室

Socket.IO

介绍

通常我们web使用的是http协议,但是 HTTP 协议有一个缺陷:通信只能由客户端发起。

所以我们需要一个可以由服务端主动发出的协议,即WebSocket。

WebSocket是HTML5新增的一种通信协议,其特点是服务端可以主动向客户端推送信息,客户端也可以主动向服务端发送信息,是真正的双向平等对话,属于服务器推送技术的一种。

Socket.IO 是一个基于 Node.js 的实时应用程序框架,在即时通讯、通知与消息推送,实时分析等场景中有较为广泛的应用。

socket.io 包含两个部分:

  • 服务器端(server):运行在 Node.js 服务器上
  • 客户端(client):运行在浏览器中

开启服务

当然,socket.IO构架在一个nodejs服务上,这里开启一个express服务。

创建文件夹socketIODemo,然后安装

    npm init -y
    npm install express --save

之后在socketIO中创建文件index.js:

    const express = require('express')
    const app = express()
    
    app.use(express.static(__dirname + '/public'));
    
    app.listen(3000, () => console.log('Example app listening on port 3000!'))

创建静态资源public/index.html :

    <!DOCTYPE html>
    <html lang="en">
    <head>
        <meta charset="UTF-8">
        <title>Document</title>
        <style>
            * {
                margin: 0;
                padding: 0;
            }
            html,
            body {
                height: 100%;
                overflow: hidden;
            }
            .chat {
                float: left;
                padding: 1em 1em 0 2em;
                height: 100%;
                width: 500px;
                border-right: 1px solid #DA4;
                overflow-y: scroll;
            }
            .inputpart {
                float: left;
                margin-left: 10px;
            }
            #userName {
                font-size: 20px;
                color: rgb(3, 57, 109);
            }
        </style>
    </head>
    <body>
        <div class="chat">
            <ul id="messages">
                //聊天信息
            </ul>
        </div>
        <div class="inputpart">
            <div id="userName">
                //用来展示用户id
            </div>
            <form action="">
                <input autocomplete="off" id="inpB" /><button id="say">Send</button>
            </form>
        </div>
    </body>
    </html>

此时开启服务: node index, 访问localhost:3000。

服务开启!

使用socket.IO

安装:

    npm install socket.io --save

然后在index.js中注册socket.io,并改为http监听:

    let http = require('http').Server(app)
    const io = require('socket.io')(http) 
    app.use(express.static(__dirname + '/public'));
    
    http.listen(3000, () => console.log('Example app listening on port 3000!'))

此时服务已改为WebSocket服务。

数据传输

服务端运行后会在根目录动态生成socket.io的客户端js文件,客户端可以通过固定路径/socket.io/socket.io.js添加引用。
在HTML中引用js文件,并调用:

        <script src="/socket.io/socket.io.js"></script>
        <script src="https://code.jquery.com/jquery-3.1.1.min.js"></script>
        <script>
            $(function () {
                var userName = '';
                while ($('#userName').text().trim() === '') {
                    //设置用户名
                    let promptName = prompt("请设置你的昵称", "")
                    userName = promptName ? promptName + ':' : '未命名:';
                    $('#userName').text(userName);
                }
                let socket = io();
                socket.on('connect', function () {
                    socket.emit('join', userName)
                })
                // 监听系统消息
                socket.on('sys', function (sysMsg) {
                    var message = '<div class="sysMsg">' + sysMsg + '</div>';
                    $('#messages').append(message);
                });
            })
        </script>

这段代码中,socket.on('connect', function () { })为默认监听事件,socket.io 提供了默认事件(如:connect, message, disconnect)。也可以自定义。socket.emit('action');表示发送了一个action命令,命令是字符串的。

后台index.js文件中:

    io.on('connection', function (socket) {
        console.log('a user connected')
        let userID = ''
        socket.on('join', function (userName) {
            userID = userName;
            io.emit('sys', userID + '已加入房间');
            console.log(userID + '加入了');
        });
    })

connection事件在客户端成功连接到服务端时触发,有了这个事件,我们可以随时掌握用户连接到服务端的信息。
当客户端成功建立连接时,在connection事件的回调函数中,我们还是可以为socket注册一些常用的事件,如:disconnect事件socket.on('disconnect',function(){...});,它在客户端连接断开是触发,这时候我就知道用户已经离开了。

重启服务,打开多个窗口,查看聊天框内容:

下面添加聊天功能。

在HTML文件中添加事件监听click:

      $('#say').click((e) => {
          e.preventDefault()
          socket.send($("#inpB")[0].value)
          $("#inpB")[0].value = ''
      })
      socket.on('msg', function (userName, userColor, msg) {
          var message = ' <div class="message">' +
              `<span class="user" style="font-size:1.5em; color: #${userColor}">` +                  userName + '</span>' +
              '  <span class="msg">' + msg + '</span>' +
              '</div>';
          $('#messages').append(message);
          // 滚动条保持最下方
          $('#messages').scrollTop($('#messages')[0].scrollHeight);
      });

这段代码中,首先监听事件并将input中内容send回去;socket.on为自定义事件msg 用来接收后台发送来的其他人的发言。

socket.emit和socket.send的区别在stackoverflow中有一个解释大意是说emit可以自定义事件,而send不可以,且只能以message接收。

后台index.js:

    io.on('connection', function (socket) {
        console.log('a user connected')
        let userID = '', userColor =parseInt(Math.random() * 16777216).toString(16)
    
        socket.on('join', function (userName) {
            userID = userName;
            io.emit('sys', userID + '已加入房间');
            console.log(userID + '加入了');
        });
        socket.on('message', function (msg){
            io.emit('msg', userID, userColor, msg)
        })
    })

为新的成员随机匹配颜色,并将message监听到的信息通过自定义为msg的事件emit出去。

此时,一个简易聊天室已经完成。

读者可以自行添加退出功能,或者设置多个房间。。。

参考代码

猜你喜欢

转载自www.cnblogs.com/coldant/p/10437220.html