使用Socket.IO仿微信聊天应用

页面布局的构建

根据网页版的微信,利用flex框架进行重建。手机版根据实际情况将聊天页面隐藏,点击相应用户的聊天室显示相应的聊天页面。

socket.io

基本原理

  • 是一个开源的WebSocket库,它通过Node.js实现WebSocket服务端,同时也提供客户端JS库。
  • 原理是基于事件的推送实现双向通讯。对于数据的处理就是一个个的事件触发。

基本语法

// send to current request socket client
socket.emit('message', "this is a test");
// sending to all clients except sender
socket.broadcast.emit('message', "this is a test");
// sending to all clients, include sender
io.sockets.emit('hi', 'everyone');
// sending to individual socketid
io.sockets.socket(socketId).emit('message', 'for your eyes only');

服务端代码实现

var server = http.createServer(app);
//// 在线用户名单
var onlineList = [];
// 创建socket服务
var io = require('socket.io').listen(server);
io.on('connection', function(socket) {
  var usr;
  //加入聊天室
  socket.on('online', function(uid) {
    //用户加入
    usr = uid;
    socket.join(usr);
    //把当前用户加入在线用户名单中
    if ( onlineList.indexOf(uid) === -1) {
      onlineList.push(uid);
    }
    console.log(usr + ' online...');
  });

  // 处理用户消息
  socket.on('message', function (uid,fid,msg) {
    var type;
    // 判断接收方是否在线
    if (onlineList.indexOf(fid) === -1) {
      //不在线将消息保存到数据库
      type = config.site.OFFLINE;//OFFLINE是1
      io.to(uid).emit('msg', uid, fid, msg);//user
    }else{
    //接收方在线,将消息发送给对方
      type = config.site.ONLINE;
      io.to(fid).emit('msg', uid, fid, msg);//(_id,fid,msg);
      io.to(uid).emit('msg', uid, fid, msg);
    }

    var data = {
      "uid":uid,
      "from":uid,
      "to":fid,
      "type":type,
      "msg":msg
    };
    console.log(data);
    //数据库存入
    dbHelper.addMsg(data, function (success, data) {
      console.log(uid + ' -> ' + fid + 'msg saved...');
    })
  });

   //非正常下线
     socket.on('disconnect', function() {
       // 从在线名单中移除
       var index = onlineList.indexOf(usr);
       if (index !== -1) {
         onlineList.splice(index,1);
         socket.leave(usr);
       }
       console.log(usr + ' offline...');
     });

  //正常下线
  socket.on('leave', function() {
    socket.emit('disconnect');
  });

});

客户端代码

//聊天区域
hello
按下enter发送

上面的html内容本身没有什么好说的,我们主要看看里面的4个文件请求
1./lib/socket.io/socket.io.js
2.common.js
3.chat.js
第1个JS是Socket.IO提供的客户端JS文件,当npm安装完socket.io并搭建起WebServer后,这个JS文件就可以正常访问了
第2个common.js主要提供一些格式处理,路径获取,消息提示这里就不再赘述
第3个chat.js是完整的客户端的业务逻辑实现代码,它的内容如下:

$(init);

function init() {
  initSocket();
  initFriendList();

  $('body').on('click', '.addFriendBtn' , doAddFreind);
  $('body').on('click', '.wrapper-content .list li' , doChatSession);
  $('body').on('keydown', '#editArea' , doSend);
}
//初始化socketio
function initSocket() {
  socket = io();
  socket.emit('online', _id);

  // 监听消息
  socket.on('msg', function(uid, fid, msg) {
    var fromID = (_id == fid)?uid:fid;
    var message;
    //当前用户如果是好友的话显示在发送方
    if (_id == fid) {
      console.log(uid+"发送信息给"+fid );
      friendThumb = $('#'+uid).children('img').attr('src');
      //前端显示接收信息
      var html = '
  • ' +msg +'

  • '; $('#messages').append(html); } else { //前端显示发送消息 var html = '
  • ' +msg +'

  • '; $('#messages').append(html); console.log("from"); } }); } //计算sessionid将较大id放置前面小的加后面,这样两个人聊天的sessionid就是唯一的 function calcuSessionId(uid,fid) { return (uid>fid)?(uid+fid):(fid+uid); } //新建会话过程 function doChatSession() { fid = $(this).attr("id"); //得到sessionid var sessionId = calcuSessionId(_id,fid); console.log(sessionId); //第一次点击的话,发送初始化session消息 if (chatSession.indexOf(sessionId) === -1) { chatSession.push(sessionId); socket.emit('join', sessionId); } //切换界面 toggleChatView(fid); } //切换聊天窗口 function toggleChatView(fid) { if ($("#message"+fid).length == 0) { $(".title_wrap .message-content").prepend('
    '); } $(".box-content").hide(); $("#message"+fid).show(); } //发送消息给朋友 function doSend(e) { if (e.which === 13) {//获取enter键 e.preventDefault(); var msg = $(this).val(); console.log(msg); $(this).val(''); // 发送消息 socket.send(_id,fid,msg); } }

    最近入的坑

    • format的constructor说undefined,通常是自己传进的参数与定义的的不一致,该函数本身是没错的
    • 加入session支持,认证机制必须依赖cookie,所以还应该同时安装一个cookie-parser,然后再app.js中导入这两个中间件,
      定义cookie解析器,注意,该定义必须写在路由分配之前.
    • 用户头像的显示
      在route文件夹下添加user: req.session.user,这样相应页面就可以调用user内的数据,通过{{user.userThumb}}和`{{user.username}}显示用户名及头像

    你可能感兴趣的:(使用Socket.IO仿微信聊天应用)