在express4上使用socket.io 1.4.6版本的心得(node.js实战读书笔记2)

跟着书来到了第二个项目,还是一如既往的坑,很少的npm的用法都不一样了,只能硬着头皮来自己研究了。
首先是引入,我的项目是直接使用express的命令来生成的,目录结构是这样的
这里写图片描述

和书里面使用的结构是不一样的,运行node的脚本在bin下面,一开始,我在项目的根目录下面的app.js里面来引入的socket.io,发现在view层使用的时候,也就是引入这句的时候死活不行,一直404

<script src="/socket.io/socket.io.js"></script>

后面发现io是要在bin/www里面引入的,www的代码如下

#!/usr/bin/env node

/**
 * Module dependencies.
 */

var app = require('../app');
var debug = require('debug')('N-chat:server');
var http = require('http');
/**
 * Get port from environment and store in Express.
 */

var port = normalizePort(process.env.PORT || '3000');
app.set('port', port);

/**
 * Create HTTP server.
 */

var server = http.Server(app);

//在这里写了io,在这里引入和写io的方法
require('../models/io')(server);
/**
 * Listen on provided port, on all network interfaces.
 */

server.listen(port);
server.on('error', onError);
server.on('listening', onListening);

/**
 * Normalize a port into a number, string, or false.
 */

function normalizePort(val) {
  var port = parseInt(val, 10);

  if (isNaN(port)) {
    // named pipe
    return val;
  }

  if (port >= 0) {
    // port number
    return port;
  }

  return false;
}

/**
 * Event listener for HTTP server "error" event.
 */

function onError(error) {
  if (error.syscall !== 'listen') {
    throw error;
  }

  var bind = typeof port === 'string'
    ? 'Pipe ' + port
    : 'Port ' + port;

  // handle specific listen errors with friendly messages
  switch (error.code) {
    case 'EACCES':
      console.error(bind + ' requires elevated privileges');
      process.exit(1);
      break;
    case 'EADDRINUSE':
      console.error(bind + ' is already in use');
      process.exit(1);
      break;
    default:
      throw error;
  }
}

/**
 * Event listener for HTTP server "listening" event.
 */

function onListening() {
  var addr = server.address();
  var bind = typeof addr === 'string'
    ? 'pipe ' + addr
    : 'port ' + addr.port;
  debug('Listening on ' + bind);
}

models/io.js的代码如下


module.exports = function (server) {
    //在这里引入了io并且写方法
    var socket = require('socket.io');
    var io     = socket.listen(server);

    //下面开始就是一些方法了
    var users  = {};

    io.on("connection" , function (socket) {
        socket.on('online',function (data) {
            socket.name = data.user;
            if (!users[data.user]) {
                users[data.user] = data.user;
            }
            io.sockets.emit('online',{users:users,user:data.user});
        })

        socket.on('say',function (data) {
            if (data.to == 'all') {
                socket.broadcast.emit('say',data);
            } else {
                //向特定用户发送信息
                //这个方法保存所有连接的对象
                var clients = io.sockets.connected;
                // console.log(clients);
                for (var i in clients) {
                    if (clients[i].name == data.to) {
                        clients[i].emit('say',data);
                    }
                }

            }
        })

        socket.on('disconnect',function () {
            if (users[socket.name]) {
                //删除改用户
                delete users[socket.name];
                //广播
                socket.broadcast.emit('offline',{users:users,user:socket.name});
            }
        })
    })

}

这就是第一个遇到而且困扰了我很久的问题。

然后介绍一下socket.io

Socket.io将Websocket和轮询(Polling)机制以及其它的实时通信方式封装成了通用的接口,并且在服务端实现了这些实时机制的相应代码。也就是说,Websocket仅仅是Socket.io实现实时通信的一个子集。
其实我的理解就是这个东西可以一直保持客户端和服务器端的通讯,特别适合用来做即时通讯。

用法其实关键是两个,一个发送一个接收,无论你是怎服务器发送还是在客户端发送,你在另外一边就可以接收到。

在服务器端Server (app.js)的的用法(使用的express框架)

var app = require('express').createServer();
var io = require('socket.io')(app);

app.listen(80);

app.get('/', function (req, res) {
    res.sendfile(__dirname + '/index.html');
});

io.on('connection', function (socket) {
    //这里就是发送
     socket.emit('news', { hello: 'world' });

     socket.on('my other event', function (data) {
        console.log(data);
     });
});

客户端Client (index.html)

<script src="/socket.io/socket.io.js"></script>
<script>
  var socket = io.connect('http://localhost');
  socket.on('news', function (data) {
    console.log(data);
    socket.emit('my other event', { my: 'data' });
  });
</script>

其实这些用法什么的在官网都可以找到,我在这里就不说了,把地址贴出来
http://socket.io/docs/

还是介绍一下我遇到的坑和一些常用方法吧

1:在服务器端找出所有客户端的连接
之前是这样的
io.sockets.clients()
现在是这样的
io.sockets.connected
2:失去连接在客户端和服务器端都有方法,但是在失去连接的那个客户端写意义不大。但是有可能我们需要告知其他客户端,我们可以在服务器端来写方法

//这个方法不需要用emit来触发,只要有客户端失去连接就会自动触发了
socket.on('disconnect',function () {
    if (users[socket.name]) {
        //删除改用户
        delete users[socket.name];
        //广播
        socket.broadcast.emit('offline',{users:users,user:socket.name});
    }
})

我们再在其他的客户端接收offline这个方法就可以了

socket.on('offline',function(data){
    //显示系统消息(这里并不重要)
    var sys = '<div style="color:#f00">系统(' + now() + '):' + '用户 ' + data.user + ' 下线了!</div>';
        $("#contents").append(sys + "<br/>");
    //刷新用户在线列表
    flushUsers(data.users);
    //如果正对某人聊天,该人却下线了
    if (data.user == to) {
        to = "all";
    }
    //显示正在对谁说话
    showSayTo();

})

3.服务器关闭和重连

//服务器关闭
socket.on('disconnect', function() {
    var sys = '<div style="color:#f00">系统:连接服务器失败!</div>';
    $("#contents").append(sys + "<br/>");
    $("#list").empty();
});

//重新启动服务器
socket.on('reconnect', function() {
    var sys = '<div style="color:#f00">系统:重新连接服务器!</div>';
    $("#contents").append(sys + "<br/>");
    socket.emit('online', {user: from});
});

其实还有很多的api在这个小项目并没接触到,地址就贴出来
http://socket.io/docs/server-api/

PS:这次这个聊天室的项目让我再一次感觉到node发展的迅速和中文资料的缺失,英语真的很重要!

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值