作者:vousiu 出處:http://www.cnblogs.com/vousiu 本實例參考自Mike Cantelon等人的《Node.js in Action》一書。 chat_server.js: 客戶端和服務端就是不斷通過socket.io事件來通信: chat_server > cha ...
作者: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 --------
清理與這個用戶相關的變數。