美文网首页程序员让前端飞Web前端之路
基于socket.io+express的聊天室demo,让你快速

基于socket.io+express的聊天室demo,让你快速

作者: darrell | 来源:发表于2018-01-27 21:28 被阅读409次

    基于socket.io+express的聊天室demo

    一,案例的效果图

    image

    1,刚刷新时出新用户名输入的input框,用于输入用户的用户信息

    image

    2,用户上线后,浏览器上线时的提示

    image

    3,聊天室群发消息

    image

    4,聊天室单发消息

    image

    5,聊天室发送图片

    具体大家可以去我的coding克隆这个项目:socket.io+express聊天室demo

    二,聊天室框架搭建

    1,因为案例是基于express的demo,可以使用官网的express应用生成器生成应用。

    npm install express-generator -g 
    

    2,在相应目录下生成文件

    express myapp
    

    3,进入这个应用,并安装相应依赖

    cd myapp 
    npm install
    

    4,紧接着运行程序

    npm start  // 或者 node ./bin/www 
    

    5,相应的目录结构如下

    .
    ├── app.js
    ├── bin
    │   └── www
    ├── package.json
    ├── public
    │   ├── css
    │   ├── images
    │   ├── javascripts
    │   ├── js
    │   ├── stylesheets
    │   └── stylesheets
    │       ├── main.css
    │       ├── style.css
    │       ├── ...
    ├── routes
    │   ├── index.js
    │   └── users.js
    └── views
        ├── error.jade
        ├── index.jade
        └── layout.jade
    

    三,聊天时的消息提示类

    使用了插件Sco.js和bootstrap的HubSpot 弹框组件库,具体的使用这里不过多的介绍,大家可以看看官方的api或者适应你自己的消息提示插件。

    四,socket.io的介绍

    1,什么是socket.io

    由于http是无状态的协议,所以实现聊天等通信功能非常困难,当别人发送一条消息时,服务器并不知道当前有哪些用户等着收消息,所以以前实现聊天通信功能最普遍的就是轮询机制了,客户端定期发一个请求,看看有没有人发送消息到服务器上了,如果有,服务器就将消息发给该客户端。

    缺点显而易见,那么多的请求消耗了大量资源,有大量的请求其实是浪费了。

    现在,我们有了WebSocket,他是HTML5的新api。 WebSocket 连接本质上就是一个 TCP 连接,WebSocket会通过http请求建立,建立后的WebSocket会在客户端和服务器端建立一个持久的连接,直到有一方主动的关闭了该连接。所以现在服务器就知道有哪些用户正在连接了,这样通讯就变得相对容易了

    Socket.io实际上是WebSocket的父集,Socket.io封装了WebSocket和轮询等方法,他会根据情况选择方法来进行通讯。

    2,在express整合socket.io

    • 首先,在根目录新建serverchat.js
    var io = require('socket.io')();
    
    exports.listen = function(_server){
        io.listen(_server);
    };
    
    • 接着在bin目录下的www文件的require(http)后引入serverchat.js
    var io = require('../serverchat');
    
    • 同时将io挂到我们的server下,并注释掉我们之前开启服务的server.listen(port);
    io.listen(server); 
    
    server.listen(port); //将这段删除或者注释
    

    这里还有一个需要注意的是,我们不能使用var server = http.createServer(app);这段代码创建一个服务了,而是需要用以下代码创建服务,否则服务启动不了。

    var server = app.listen(app.get('port'), function() {
      debug('node_chat server listening on port ' + server.address().port);
    });
    

    五,socket.io的连接,断开。

    1,在服务器端

    serverchat.js中,我们处理相关的关于socket.io的代码

    io.on('connection',function(socket){
      socket.on('disconnect',function(){
        });
    }) // 使用这段代码进行socket的连接
    

    这里我们要注意的是接下去我们要做的关于信息发送等操作,都是要在连接的前提下建立的,只有当我们连接了socket之后,我们才能做我们想让socket为我们做的事情。

    2,在客户端中

    我们在public/javascript下建立两个文件,chat.jsclient.js

    chat.js中我们主要做的事接受服务端请求,并通过client.js中的关于jq的处理页面相关的方法。

    这里我们大可以把所有的js写在一个文件中,但是我们分成两个写的话,会是代码更佳移动,好维护。

    3,接下来在index.jade中引入这两个js

    script(src='/javascripts/chat.js')
    script(src='/javascripts/client.js')
    

    这里说到的关于jade的语法,大家如果还不是特别熟的话,可以去参考jade官网,里面有详细的介绍。

    六,用户登录

    这里的登录是假登录,我们只是需要获取用户input框里面输入的姓名以及用户的头像图片。

    1,客户端

    当用户在输入框中输入名字,确定之后,客户端会发一个信息给服务端,socket通过emit这个函数发送信息,通过on这个函数接受信息。

    client.js

    // 用户登录
        $('#btn-setName').click(function(){
            var name = $('#username').val();
            console.log(name);
    
            if(checkUser(name)){
                $('#username').val('');
                alert('Nickname already exists or can not be empty!');
            } else {
                // 随机头像
                var imgList = ["/images/1.jpg","/images/2.jpg","/images/3.jpg","/images/4.jpg","/images/5.jpg"];
                var randomNum = Math.floor(Math.random()*5);
    
                var img = imgList[randomNum];
                
                // 发送到服务端的用户信息数据
                var dataObj = {
                    name:name,
                    img:img
                };
                
                socket.emit('login',dataObj);
                // 隐藏modal
                
                $('#myModal').modal('hide');
                $('#username').val('');
                $('#msg').focus();
            }
        })
    

    2,服务端

    得到客户端传过来的数据,将用户信息塞入到服务端的userList,服务器将新的userList发送给各个客户端。

    var userList = [];
    
    socket.on('login', function(user){
        user.id = socket.id;
        userList.push(user);
        
        io.emit('userList',userList); // 发送给所有的用户
        socket.emit('userInfo',user); // 发送给自己
        socket.broadcast.emit('loginInfo',user.name+"上线了。"); 
        //发送给出自己外的用户
    });
    

    3,客户端

    chat.js中接收userList,客户端接受到新的userList的时候,渲染新的用户聊天室列表,在接受到新的userInfo的时候在列表左侧显示相应的“欢迎你,用户名”字样。

    // 用户列表渲染
    socket.on('userList',function(userlist){
        addUser(userlist);
    })
    // 用户信息渲染
    socket.on('userInfo',function(userObj){
        //should be use cookie or session
        userSelf = userObj; // 真实的登录应该把用户信息存在session里。
      $('#spanuser').text('欢迎您! '+userObj.name);
    })
    

    至此,我们便完成一个简单的socket的数据的交互。

    七,发送单聊与群聊

    • 群聊,比较简单,我们可以通过socket广播socket.broadcast.emit(),发送给除自己以外的用户。
    socket.on('toAll',function(msgObj){
        socket.broadcast.emit('toAll',msgObj); 
    });
    
    • 单聊,刚刚我们讲过socket.emit()是发送信息给自己,每一个socket有自己的id,我们只需要将socket的id变成我们要发送的那个用户的id,我们就能实现单聊了。
    socket.on('toOne',function(msgObj){
        var toSocket = _.findWhere(io.sockets.sockets,{id:msgObj.to});
        toSocket.emit('toOne', msgObj);
    })
    

    上面的 - 是我们引用的 underscore ,处理数据的一个库。具体可以查看underscore中文文档,通过npm install underscore --save安装依赖。同时我们可以通过 io.sockets.sockets 获取所有的socketid

    八,如何发送图片

    我们可以通过h5的api——FileReader(),这个api会将图片转化为base64格式的,然后就可以进行发送了,

    1,客户端

    //send image to all
      $('#sendImage').change(function(){
        if(this.files.length != 0){
            var file = this.files[0];
            reader = new FileReader();
            if(!reader){
                alert("!your browser doesn\'t support fileReader");
                return;
            }
            reader.onload = function(e){   // 加载文件
                var msgObj = {
                    from:userSelf,
                    img:e.target.result
                };
                socket.emit('sendImageToALL',msgObj); 
                addImgFromUser(msgObj,true);
            };
            reader.readAsDataURL(file);  // 将图片转化为base64格式的
        }
      });
    

    2,服务端

    将信息发送给客户端,客户端转发给除了自己的其他socket用户

    //sendImageToALL
    socket.on('sendImageToALL',function(msgObj){
        socket.broadcast.emit('sendImageToALL',msgObj);
    })
    

    3,客户端

    chat.js中接受相应的图片socket信息,

    socket.on('sendImageToALL',function(msgObj){
      addImgFromUser(msgObj,false);
    });
    

    client.js 中,将图片进行相应的dom操作,将图片渲染进去。 base64 格式的也可以通过 <img src="" /> 标签中的src进行渲染。

    九,对于文章的一些说明

    1,此篇文章的demo是我在学习一个socket.io视频时的demo做的,非常感谢这个老师的视频。

    2,我写这篇文章的目的是希望能给没有时间去看视频学习,同时又懒得去看文档的小伙伴们一个快速了解 socket.io 制作聊天室。

    3,如需要这个视频的小伙伴,可以在私信我向我要。

    4,文章可能会存在很多问题,欢迎小伙伴批评指正哦

    相关文章

      网友评论

        本文标题:基于socket.io+express的聊天室demo,让你快速

        本文链接:https://www.haomeiwen.com/subject/edeoaxtx.html