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">< ...
随机推荐
- php编写tcp服务器和客户端程序
这是我从别的地方看到的. 1.修改php.ini,打开extension=php_sockets.dll 2.客户端程序 SocketClient.php <?php set_time_limi ...
- cms 常用标签
{template "content","header"} 调用根目录下phpcms\template\content\header文件 {CHARSET} 字 ...
- 实验三——for语句及分支结构else-if
1.本节课学习到的知识点: (1)for语句是循环语句,它可以实现c语句的重复执行 (2)for语句中的3个表达式的执行顺序和书写顺序不同 (3)遇到复合语句时要用大括号将几句话括起来,复合语句在语法 ...
- 5-Zend Studio配置
0-将文件编码设置成utf-8 Window>Preferences>General>Content Types>Text Default encoding:utf-8 1-Z ...
- C# 创建Windows服务
创建windows服务项目 2 右键点击Service1.cs,查看代码, 用于编写操作逻辑代码 3 代码中OnStart用于执行服务事件,一般采用线程方式执行方法,便于隔一段事件执行一回 END ...
- 前端构建 build 技术 nodejs gulp
https://www.sitepoint.com/introduction-gulp-js/ 参照这个例子做一遍,就会明白,中间会有个问题 npm install jshint 需要修正为 npm ...
- linux(centos)用户与权限
1.用户管理 2.用户组 3.权限分配 一.查看与用户相关文件命令: 1.cat 2.more 3.head /etc/passwd #查看文件的前十行 4.head -2 /etc/passw ...
- iOS 解决图片上传到服务器旋转90度的问题(图片倒置)
//使用swift的朋友们可以,把这个所在的类的.h,在-Header-Swift.h中一用一下. - (UIImage *)fixOrientation:(UIImage *)aImage { if ...
- List 用法和实例(转载)
写在粘贴复制前:英文的感觉也可以,也能看的懂,多看看英文资料没坏处的 Problem. You have questions about the List collection in the .NET ...
- HTML总结笔记
1.select标签取值问题: <select id="selector"> <option value="A" selected >a ...