照着书上的代码敲了一遍聊天室程序,功能比较复杂,包括新房间的创建,房间的切换,名称的更改等。逻辑较为简单,辅助函数也没有什么高级用法,但港真,在recoding之前,我竟然不知道,前后端的交互接口,或者说前端的socket是如何同后端搭上线的(原谅我是个刚入门的菜j)。
思路如下:
1、首先要给client提供静态文件服务,即请求的html、css、js等文件。
2、在服务器端处理与聊天相关的消息。
3、在客户端(浏览器中js引擎)处理与聊天相关的消息。
附上github地址:https://github.com/StarInworld/ChatRoom
首先在服务器端创建http服务器逻辑(静态文件服务可见github)。
//http服务器逻辑
var server = http.createServer(function(req, res) {
var filePath = false;
if (req.url === '/') {
filePath = 'public/index.html';
} else {
filePath = 'public' + req.url;
}
var absPath = './' + filePath;
serveStatic(res, cache, absPath);
});
server.listen(3000, function() {
console.log('Server listening on port 3000.');
});
//引用socket服务器,看下一步
var chatServer = require('./lib/chat_server');
//给socket服务器提供一个http服务器,这样他可以跟http服务器共享同一个TCP/IP端口
chatServer.listen(server);
而后在服务器端利用socket.io处理聊天相关消息。
设置socket.io服务器
var socketio = require('socket.io');
var io;
var guestNumber = 1;
var nickNames = {};
var namesUsed = [];
var currentRoom = {};
exports.listen = function(server) {
io = socketio.listen(server);
io.set('log level', 1);
//定义每个用户连接的处理逻辑
io.sockets.on('connection', function(socket) {
//在用户连接上来时赋予其一个用户名
guestNumber = assignGuestName(socket, guestNumber, nickNames, namesUsed);
//在用户连接上来时把他放入聊天室Lobby中
joinRoom(socket, 'Lobby');
//处理用户的信息,更名,以及聊天室的创建和变更
handleMessageBroadcasting(socket, nickNames);
handleNameChangeAttempts(socket, nickNames, namesUsed);
handleRoomJoining(socket);
//用户发送请求时向其提供已经被占用的聊天室的列表
socket.on('rooms', function() {
socket.emit('rooms', io.sockets.manager.rooms);
});
//定义用户断开连接后的清除逻辑
handleClientDisconnection(socket, nickNames, namesUsed);
});
};
注意这里io.sockets.on(‘connection’,function(){}),这是与客户端实现连接的关键。即定义了客户端连接成功后的处理逻辑。是socket.io默认的方法,不需要自定义即可使用。
最后,在客户端添加js。
首先定义一个js“类”,在初始化时传入一个socket.io的参数socket,具体类的方法可见github。
var Chat = function(socket){
this.socket = socket;
};
其次,在客户端初始化程序处理聊天信息的socket逻辑。
var socket = io.connect();
$(document).ready(function(){
var chatApp = new Chat(socket);
...
})
想必你已经发现了,这里与服务器端实现连接的方式,便是通过socket.io的方法io.connect(url),url不填即为当前路径,io.connect()获取socket对象,接着就可以使用socket来收发事件。
简单介绍一些常用的API:
服务器端事件:
io.sockets.on(‘connection’, function(socket) {}):socket连接成功之后触发,用于初始化
socket.on(‘message’, function(message, callback) {}):客户端通过socket.send来传送消息时触发此事件,message为传输的消息,callback是收到消息后要执行的回调
socket.on(‘anything’, function(data) {}):收到任何事件时触发
socket.on(‘disconnect’, function() {}):socket失去连接时触发(包括关闭浏览器,主动断开,掉线等任何断开连接的情况)
客户端事件:
connect:连接成功
connecting:正在连接
disconnect:断开连接
connect_failed:连接失败
error:错误发生,并且无法被其他事件类型所处理
message:同服务器端message事件
anything:同服务器端anything事件
reconnect_failed:重连失败
reconnect:成功重连
reconnecting:正在重连
在这里要提下客户端socket发起连接时的顺序。当第一次连接时,事件触发顺序为:connecting->connect;当失去连接时,事件触发顺序为:disconnect->reconnecting(可能进行多次)->connecting->reconnect->connect。