Node聊天程序实例02:chat_server.js
作者:vousiu
出处:http://www.cnblogs.com/vousiu
本实例参考自Mike Cantelon等人的《Node.js in Action》一书。
chat_server.js:
客户端和服务端就是不断通过socket.io事件来通信:
chat_server ---------------> chat_ui
chat_server <--------------- chat_ui
其中的这一段:
socket.on('rooms', function() { socket.emit('rooms', io.sockets.manager.rooms); });
注册异步回调函数:
<--------------- 'rooms' ------------------
|
`------------- 'rooms' ---------------> 全部房间。
这段代码与客户端定时请求所有房间号相配合,不断刷新可用房间列表。其实也可以在用户开新房间时再对所有用户广播,那样就不用定期刷新了。但是那样的话当最后一个用户离开原房间时,那个房间不会消失。
function assignGuestName(socket, guestNumber, nickNames, nameUsed) { var name = 'Guest' + guestNumber; nickNames[socket.id] = name; socket.emit('nameResult', { success: true, name: name }); nameUsed.push(name); return guestNumber + 1; }
chat_server ----------- 'nameResult' ------------> {success: true, name:'Guestxxx'}
更新服务器里与name有关的变量。
(用户还没收到该事件消息,服务器就继续执行后面的代码操作也没事,因为服务器这里的已经存储了每个用户的名称状态,它是一致的。)
我觉得这里后三个参数不需要传,因为它们本来就是服务器本地数据,传和不传都是一样的,而且这个函数不是异步函数,是立即执行的。如果是异步函数,反倒会造成不一致的情况。
function joinRoom(socket, room) { socket.join(room); currentRoom[socket.id] = room; socket.emit('joinResult', {room: room}); socket.broadcast.to(room).emit('message', { text: nickNames[socket.id] + ' has joined ' + room + '.' }); var usersInRoom = io.sockets.clients(room); if (usersInRoom.length > 1) { var usersInRoomSummary = 'Users currently in ' + room + ': '; for (var index in usersInRoom) { var userSocketId = usersInRoom[index].id; usersInRoomSummary + nickNames[userSocketId] + ' '; } } socket.emit('message', {text: usersInRoomSummary}); }
更新与room相关的本地变量。
把当前socket的用户加入socket的'roomName'分组。
chat_server ----------- 'joinResult' ------------> {room: 'roomName'}
chat_server --------- (broadcast) 'message' ----------> {text: '当前用户名 has joined roomName.'}
(这句待议,为什么是由socket来broadcast而不是io?)
同步获取房间里所有的人名。
chat_server ----------- 'message' ------------> {text: '房间内所有人名'}
function handleMessageBroadcasting(socket) { socket.on('message', function(message) { socket.broadcast.to(message.room).emit('message', { text: nickNames[socket.id] + ': ' + message.text }); }); }
注册异步回调函数。
<--------------- 'message' ------------------ message
|
`------------- (broadcast:message.room) 'message' ---------------> {text: 'nickName: message'}
function handleNameChangeAttempts(socket, nickNames, nameUsed) { socket.on('nameAttempt', function(name) { if (name.indexOf('Guest') == 0) { socket.emit('nameResult', { success: false, message: 'Name cant begin with Guest' }); } else { if (nameUsed.indexOf(name) == -1) { var previousName = nickNames[socket.id]; var previousNameIndex = nameUsed.indexOf(previousName); nameUsed.push(name); nickNames[socket.id] = name; delete nameUsed[previousNameIndex]; socket.emit('nameResult', { success: true, name: name }); } else { socket.emit('nameResult', { success: false, message: 'Name already used.' }); } } }); }
注册异步回调函数。
<--------------- 'nameAttempt' ------------------ name
|
`------------- 'nameResult' ---------------> {success: true||false, message: 'name'||'why fail'}
跟前面那个回调函数不一样,这个回调函数需要服务器全局变量和对其进行修改。
同理,这里后两个参数传的是引用,传跟不传也没什么不同。(是不传就无法访问吗?)
function handleRoomJoining(socket) { socket.on('join', function(room) { socket.leave(currentRoom[socket.id]); joinRoom(socket, room.newRoom); }); }
注册异步回调函数。
<--------------- 'join' ------------------ room
|
socket离开原来的分组
|
joinRoom(socket, room.newRoom)
这个也需要服务器全局变量,它就没有传参。
function handleClientDisconnection(socket) { socket.on('disconnect', function() { var nameIndex = nameUsed.indexOf(nickNames[socket.id]); delete nameUsed[nameIndex]; delete nickNames[socket.id]; }) }
注册异步回调函数。
<------ x ------- 'disconnect' ------- x --------
清理与这个用户相关的变量。
Node聊天程序实例02:chat_server.js的更多相关文章
- Node聊天程序实例01
作者:vousiu 出处:http://www.cnblogs.com/vousiu 本实例参考自Mike Cantelon等人的<Node.js in Action>一书. 本实例要实现 ...
- Node聊天程序实例04:chat_ui.js
作者:vousiu 出处:http://www.cnblogs.com/vousiu 本实例参考自Mike Cantelon等人的<Node.js in Action>一书. 这个程序在客 ...
- Node聊天程序实例03:chat.js
作者:vousiu 出处:http://www.cnblogs.com/vousiu 本实例参考自Mike Cantelon等人的<Node.js in Action>一书. chat.j ...
- Node聊天程序实例06:server.js
作者:vousiu 出处:http://www.cnblogs.com/vousiu 本实例参考自Mike Cantelon等人的<Node.js in Action>一书. server ...
- Node聊天程序实例05:index.html和style.css
作者:vousiu 出处:http://www.cnblogs.com/vousiu 本实例参考自Mike Cantelon等人的<Node.js in Action>一书. index. ...
- 小程序实例:用js方法splict()、indexOf()、push()、replace()等操作数组Array的增删改查
一.增加数组子级 1.Array.push() 定义和用法 向数组的末尾处添加一个或多个子集,并返回新数组的长度 语法 var array=["好","扎在那个" ...
- WinSocket聊天程序实例(多线程)
#pragma comment(lib,"Ws2_32.lib") #include <stdio.h> #include <Winsock2.h> SOC ...
- boost asio异步读写网络聊天程序client 实例具体解释
boost官方文档中聊天程序实例解说 数据包格式chat_message.hpp <pre name="code" class="cpp">< ...
- boost asio异步读写网络聊天程序客户端 实例详解
boost官方文档中聊天程序实例讲解 数据包格式chat_message.hpp <pre name="code" class="cpp">< ...
随机推荐
- Dapper
前一段做一个技术分享关于dapper的,现在再总结一下,也好长时间没有更新博客了--,用到的东西 Dapper.AutoFac .AutoMapper.FluentValidation: 下面说一下D ...
- windows下的host文件在哪里?做什么用的?
在Window系统中有个Hosts文件(没有后缀名),在Windows98系统下该文件在Windows目录,在Windows2000/XP系统中位于C:\Winnt\System32\Drivers\ ...
- VB中键盘每个按键所对应的具体数值是?
键码常数 值 描述 vbKeyLButton 1 鼠标左键 vbKeyRButton 2 鼠标右键 vbKeyCancel 3 CANCEL 键 vbKeyMButton 4 鼠标中键 vbKeyBa ...
- 【转】lower_case_table_names=1 让MySQL不区分大小写
lower_case_table_names=1 让MySQL不区分大小写! 此前有款网络游戏的数据库是采用MySQL.操作系统是CentOS.部分服务器的操作系统又是Windows. 出现了一个小毛 ...
- Jquery插件Ztree使用所遇问题
问题1.$.fn.zTree为空或为Undefined 我在MVC中引用Jquery插件Ztree的JS并不存任何问题,而当我将Ztree的js引入项目中,就出现$.fn.zTree为空或为Undef ...
- java第二次作业
这次通过学习,我掌握了下拉菜单和单选按钮的使用下拉菜单构造方法:JComboBox() 创建具有默认数据模型的 JComboBox.JComboBox(ComboBoxModel aModel) 创建 ...
- eclipse连hadoop2.x运行wordcount 转载
转载地址:http://my.oschina.net/cjun/blog/475576 一.新建java工程,并且导入hadoop相关jar包 此处可以直接创建mapreduce项目就可以,不用下面折 ...
- Mac中安装node.js和npm
换了Mac需要安装noed.js和npm记录一下首先访问node.js官网(https://nodejs.org/en/download/) 点击下载完后,一路点安装 就安装完成了 然后打开-终端-输 ...
- Android线程中设置控件
在Android中经常出现多线程中设置控件的值报错的情况,今天教大家封装一个简单的类避免这样的问题,同样也调用实现也非常的方便. 自定义类: /** * Created by wade on 2016 ...
- Unity3D心得分享
本篇文章的内容以各种tips为主,不间断更新 系列文章 =========================== "Unity测试系列"文章索引 Unity-Animator深入系列 ...