使用socket.io+express实现网页聊天的实践
2014-02-26 19:04
585 查看
近期,有客户提出希望尝试用HTML5相关技术实现在线交互和文件传输,于是乎找到了socket.io,通过搜索引擎和官方帮助实现了简单的聊天和指定用户的消息广播,在此总结跟大家分享。
A.环境安装与配置
首先,安装nodejs,直接官网下载对应平台对应版本即可。地址为http://nodejs.org/安装,我安装的是Mac版的dmg。
接下来就可以使用终端来安装socket.io和express模块,命令如下:
node.js提供了高效的服务端运行环境,为了解决浏览器的兼容性问题,同时提供客户端与服务端一致的编程体验,于是socket.io诞生了。
socket.io
是一个为实时应用提供跨平台实时通信的库,包括服务器端和客户端。socket.io 旨在使实时应用在每个浏览器和移动设备上成为可能,模糊不同的传输机制之间的差异。只要在服务器端启动服务端js脚本(node app.js),就在某个端口开启了一个实时监听的通道,只要客户端连接就可以进行相互通讯。下面是官网socket.io使用的最简单示例:
环境搭建好之后,构思应用场景,客户端页面加载完成后,自动创建一个用户名(可以是登陆名),然后跟服务器端通讯,发送用户名,服务器端广播欢迎用户的消息,同时纪录用户名称和ip等信息。正常聊天时可以通过广播机制发送消息,每一个人员都可收听的到,而特殊情况可以@用户名只将消息发送给指定的用户群(room机制)。同时,在用新用户登陆或者离开是,系统需要更新每个用户的用户列表并广播用户退出的信息。
服务端主要代码
因为nojo可以直接运行js,所以开发应用可phonegap打包到不同平台,同时也可以支持在线的访问。
客户端
与服务器端对应的响应代码
参考资料
cnodechat聊天室设计及实现介绍
A.环境安装与配置
首先,安装nodejs,直接官网下载对应平台对应版本即可。地址为http://nodejs.org/安装,我安装的是Mac版的dmg。
接下来就可以使用终端来安装socket.io和express模块,命令如下:
sudo sh npm install -g socket.io npm install -g expressB.socket.io简介
node.js提供了高效的服务端运行环境,为了解决浏览器的兼容性问题,同时提供客户端与服务端一致的编程体验,于是socket.io诞生了。
socket.io
是一个为实时应用提供跨平台实时通信的库,包括服务器端和客户端。socket.io 旨在使实时应用在每个浏览器和移动设备上成为可能,模糊不同的传输机制之间的差异。只要在服务器端启动服务端js脚本(node app.js),就在某个端口开启了一个实时监听的通道,只要客户端连接就可以进行相互通讯。下面是官网socket.io使用的最简单示例:
SERVER var io = require('socket.io').listen(80); io.sockets.on('connection', function (socket) { socket.emit('news', { hello: 'world' }); socket.on('my other event', function (data) { console.log(data); }); }); CLIENT <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>C.使用socket.io和express构建网页聊天室
环境搭建好之后,构思应用场景,客户端页面加载完成后,自动创建一个用户名(可以是登陆名),然后跟服务器端通讯,发送用户名,服务器端广播欢迎用户的消息,同时纪录用户名称和ip等信息。正常聊天时可以通过广播机制发送消息,每一个人员都可收听的到,而特殊情况可以@用户名只将消息发送给指定的用户群(room机制)。同时,在用新用户登陆或者离开是,系统需要更新每个用户的用户列表并广播用户退出的信息。
服务端主要代码
//记录在线用户 var userList={}; //记录IP var ipList={}; //WebSocket连接监听 io.on('connection', function (socket) { socket.emit('open');
// 打印连接信息 var address = socket.handshake.address; console.log("New connection from " + address.address + ":" + address.port); // 构造客户端对象 var client = { socket:socket, name:false } // 对message事件的监听 socket.on('message', function(msg){ var obj = {time:getTime()}; // 判断是不是第一次连接,消息为用户名称 if(!client.name){ client.name = msg; obj['text']=msg; obj['author']='System'; obj['type']='welcome'; console.log(client.name + ' login'); var usertxt=client.name; //纪录用户和ip信息,用于房间用户筛选,局部通讯 if (!userList[usertxt]) { userList[usertxt] = 1; } else { userList[usertxt] ++; } ipList[socket.handshake.address.address]=usertxt; //返回欢迎语 socket.emit('system',obj); //广播新用户已登陆 socket.broadcast.emit('system',obj); var objusr = {time:getTime()}; objusr['text']=userList; objusr['author']='System'; objusr['type']='userConnected';
//更新用户列表 io.sockets.emit('system',objusr); }else{ //如果不是第一次的连接,正常的聊天消息 obj['text']=msg; obj['author']=client.name; obj['type']='message'; console.log(client.name + ' say: ' + msg); var arr=msg.split("@"); //将消息用@符号进行分割,筛选出关联的在线用户 if(arr.length<3 || arr[0]!="") { // 返回消息(可以省略) socket.emit('message',obj); // 广播向其他用户发消息 socket.broadcast.emit('message',obj); } else { var flag=0;
//根据用户名称找到用户对应ip地址,再通过ip地址找到对应的socket连接,将@关联的用户socket加入到一个room中 io.sockets.clients().forEach(function (socket) { for(ip in ipList) { for(i=0;i<arr.length;i++) { if(ipList[ip]==arr[i] && ip==socket.handshake.address.address) { //加入到指定房间
socket.join('someUsers'); flag++; } } } }); if(flag==0) { socket.join('me'); obj['text']="请核实您关联的用户名!"; obj['author']='系统'; io.sockets.in('me').emit('message', obj); } else { obj['text']=arr[arr.length-1];
//将消息发送给加入该房间的用户
io.sockets.in('someUsers').emit('message', obj); } } } }); //监听出退事件 socket.on('disconnect', function () { var obj = { time:getTime(), color:client.color, author:'System', text:client.name, type:'disconnect' }; var userName=client.name; if (userList[userName]) { userList[userName] --; if (userList[userName] == 0) { delete userList[userName]; } } for(ip in ipList) { if (ipList[ip]==client.name) { delete ipList[ip]; } console.log(ip); } // 广播用户已退出 socket.broadcast.emit('system',obj); console.log(client.name + 'Disconnect'); var objusr = {time:getTime()}; objusr['text']=userList; objusr['author']='System'; objusr['type']='userConnected'; socket.broadcast.emit('system',objusr); });其次,express的简单配置
//express基本配置 app.configure(function(){ app.set('port', process.env.PORT || 3000); app.set('web', __dirname + '/web'); app.use(express.favicon()); app.use(express.logger('dev')); app.use(express.bodyParser()); app.use(express.methodOverride()); app.use(app.router); app.use(express.static(path.join(__dirname, 'public'))); }); app.configure('development', function(){ app.use(express.errorHandler()); }); // 指定webscoket的客户端的html文件 app.get('/', function(req, res){ res.sendfile('web/index.html'); }); server.listen(app.get('port'), function(){ console.log("Express server listening on port " + app.get('port')); });
因为nojo可以直接运行js,所以开发应用可phonegap打包到不同平台,同时也可以支持在线的访问。
客户端
与服务器端对应的响应代码
var $chars = 'ABCDEFGHJKMNPQRSTWXYZabcdefhijkmnprstwxyz2345678'; var maxPos = $chars.length; var usr = ''; for (i = 0; i < 6; i++) { usr += $chars.charAt(Math.floor(Math.random() * maxPos)); } var userName=usr; //建立websocket连接 socket = io.connect('http://192.168.0.23:3000'); socket.send(userName); //收到server的连接确认 socket.on('open',function(json){ status.text(json); }); //监听system事件,判断welcome或者disconnect,打印系统消息信息 socket.on('system',function(json){ var p = ''; if (json.type === 'welcome'){ if(userName==json.text) status.text(userName + ':'); p = '系统@'+ json.time+ ':欢迎' + json.text +'!\n'; var txt=content.val(); content.text(txt+p); }else if(json.type=='userConnected') { p=json.text; var usrlist=''; for(usr in p) usrlist=usrlist+usr+'\n'; userlist.html(usrlist); } else if(json.type == 'disconnect'){ p = '系统@'+ json.time+ ':再见' + json.text +'!\n'; var txt=content.val(); if(json.text=='false') return; else content.text(txt+p); } }); //监听message事件,打印消息信息 socket.on('message',function(json){ var p = json.author+'@'+ json.time+ ' : '+json.text + '\n'; var txt=content.val(); content.html(txt+p); }); //通过“回车”提交聊天信息 input.keydown(function(e) { if (e.keyCode === 13) { var msg = $(this).val(); if (!msg) return; socket.send(msg); $(this).val(''); if (userName === false) { userName = msg; } } });
参考资料
cnodechat聊天室设计及实现介绍
socket.io 简介及使用
相关文章推荐
- 使用Express + Socket.io + MongoDB实现简单的聊天
- 使用express + socket.io实现多房间聊天应用
- node.js实现即时聊天室,使用模块(express+socket.io),附源码
- 基于socket.io+express实现多房间聊天
- socket.io 实现网页聊天
- NodeJS+Socket.io+ExpressJS实现web聊天应用
- 基于Express+Socket.io+MongoDB的即时聊天系统的设计与实现
- 基于socket.io+express实现多房间聊天
- 详解如何使用koa实现socket.io官网的例子
- 如何在node的express中使用socket.io
- 使用C/C++实现Socket聊天程序(代码+实验报告)
- node.js + express 使用socket.io 客户端出现socket.io.js 404的问题解决
- 使用websocket的组件socket.io实现最简单的聊天室功能。
- (32)--使用Socket--udp实现简单的聊天软件
- 使用node.js + socket.io + redis实现基本的聊天室场景
- 三种获取网页源码的方法(使用MFC/Socket实现)
- 安卓SocketIO+Node.js实现好友与好友间的实时聊天
- 使用Socket实现简单聊天
- 基于Socket.IO实现Android聊天功能代码示例
- 使用nodejs+express+socketio+mysql搭建聊天室