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

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

一,案例的效果图

image

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

基于socket.io+express的聊天室demo,让你快速上手socket.io_第1张图片
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 格式的也可以通过 标签中的src进行渲染。

九,对于文章的一些说明

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

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

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

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

你可能感兴趣的:(基于socket.io+express的聊天室demo,让你快速上手socket.io)