WebSocket的应用实例

因为大多数的应用实例都是聊天室,在这个基础上做个拓展,建立一个问答形式的应用。主要规则就是提出问题,并且问题必须是可以用“是”或者“不是”来回答的。

服务端

提问和回答的人各有一个就足够了,所以这个问答聊天室应该是划分为多个房间。房间作为独立的一个功能,可以从业务逻辑中分离出来,所以在组件中新建一个room的模块

1
2
3
4
5
6
var Room = function() {
this.users = []
this.ques = []
}
module.exports = Room

房间的功能应该包括了:

  • 加入用户
  • 移除用户
  • 给房间中所有用户发送消息
  • 添加问题
  • 更新问题答案
  • 其他

为Room原型添加方法

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
Room.prototype = {
addUser: function(id) {
if (this.users.indexOf(id) !== -1) {
return;
}
if (!!id) {
this.users.push(id)
}
},
addQues: function(obj) {
if (this.ques.length <= 20) {
this.ques.push(obj)
return true;
} else {
return false;
}
},
getQuesLen: function(){
return this.ques.length
},
addAns: function(index, ans) {
this.ques[index].a = ans
},
clear: function() {
this.users.length = 0
this.ques.length = 0
}
}

Room完成后就可以在main.js中作为模块导入,

1
var Room = require('./component/room')

除此之外,对于每个新创建的房间都需要保存它的名称和实例,因此再添加

1
2
var playload = {},
rooms = {};

准备工作做好了之后,接下来就是如何使用了

在每个用户连接的时候保存用户的基本信息以及ws实例,为了唯一的识别用户,因此引入uuid
使用npm install uuid安装后,在main.js中引入

1
var uuidV4 = require('uuid/v4')

每个用户连接的时候为其分配一个标识uuid作为key保存在playload中

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
wss.on('connection', function(ws) {
var uuid = uuidV4();
var obj = {
type: 'init',
id: uuid,
role: 0
}
ws.send(JSON.stringify(obj))
obj.ws = ws;
playload[uuid] = obj;
ws.on('message', function(message) {
console.log('received: %s', message)
msgParse(message)
})
ws.on('close', function(res) {
console.log('close')
});
})

相当于是用户在第一次连接的时候获取身份id,以后在每次请求的时候都带上自己的信息;房间号获取的方式是由客户端传递过来的,因为用户可以选择加入一个房间或者创建一个房间。

房间需要有通知消息的功能,因此再添加了单独和房间的发送通知方法

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
wss.roomNotify = function(data, room) {
var msg = JSON.stringify(data)
var users = rooms[room].getUser()
users.forEach(function(item) {
if (typeof playload[item] !== 'undefined') {
playload[item].ws.send(data)
}
})
}
wss.singleNotify = function(data, uuid) {
var msg = JSON.stringify(data)
playload[uuid].ws.send(msg)
}

处理好了基本功能后就可以对客户端返回的信息进行解析了

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
function msgParse(res) {
var data = JSON.parse(res)
var room = data.room;
var uuid = data.id;
var oRoom = rooms[room]
if (data.type == 'init') {
if (typeof oRoom == 'undefined') {
rooms[room] = new Room()
oRoom = rooms[room]
}
oRoom.addUser(uuid)
} else if (data.type == 'ques') {
var obj = { q: data.msg, a: '' }
if (oRoom.addQues(obj)) {
var msg = {
type: 'ques',
msg: data.msg,
index: oRoom.getQuesLen()
}
wss.roomNotify(msg, room)
} else {
var msg = {
type: 'info',
msg: '超过最大提问数'
}
wss.singleNotify(msg, uuid)
}
} else if (data.type = 'ans') {
oRoom.addAns(data.index, data.msg)
}
}

客户端

待更新……