您的位置:首页 > Web前端 > Node.js

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

2016-07-26 23:38 387 查看
跟着书来到了第二个项目,还是一如既往的坑,很少的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);
});
ba3e
});


客户端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发展的迅速和中文资料的缺失,英语真的很重要!
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签:  node.js