npm install --save websocket
server.js
const http = require('http');
const ws = require('websocket').server;
// 建立server 並監聽Port 9999
const PORT = 9999;
const server = http.createServer().listen(PORT)
// 產生websocketServer
webSocketServer = new ws({
httpServer: server
});
//當使用者連入時 觸發此事件
webSocketServer.on('request', request => {
const connection = request.accept('echo-protocol', request.origin);
//當websocket server收到訊息時 觸發此事件
connection.on('message', event => {
let data = JSON.parse(event.utf8Data)
console.log(`接收訊息${ JSON.stringify(data) }`)
switch (data.type) {
case 'connect':
console.log(`user: ${ data.userName },\n
connect on: ${ new Date(data.date) }`)
break;
default:
break;
}
// connection.send("收到訊息: " + message.utf8Data);
});
//當使用者socket連線中斷時 例如:關閉瀏覽器 觸發此事件
connection.on('close', (reasonCode, description) => {
console.log('connection close.');
});
});
接著啟動伺服器
node server.js
注意 'echo-protocol' 此字串為和client端約定的協議, client端可以一次發送許多不同協議進行連線, 一個server端也可以一次處理多個不同的協議, 以應付不同的互動狀態
//建立WebSocket 連到127.0.0.1 Port為9999
//echo-protocol為約定好的自訂protocol 在WebSocket Server端也要設定
const mySocket = new WebSocket("ws://127.0.0.1:9999", "echo-protocol");
//Socket接收訊息時會呼叫此函數,處理接收到的訊息
mySocket.onmessage = e => {
console.log(e.data)
}
mySocket.onopen = e => {
let data = {
type: 'connect',
userName: this.userName,
date: Date.now()
}
mySocket.send(JSON.stringify(data))
}
mySocket.onclose = e => {
console.log('與伺服器失去連線')
}
建立WebSocket物件時, 第二個參數 "echo-protocol", 可以傳入一個陣列, 處理不同的互動情形
在接收websocket訊息的callback中取得狀態'is_match'後, 可以確保雙方玩家都已經加入遊戲,
此時已經可以向server發出訊息'getQuestion'取得題目
case 'isMatch':
console.log('已經加入遊戲!')
setTimeout(() => {
mySocket.send(JSON.stringify({
type : 'getQuestion',
id : data.id,
userName: VM.userName
}))
}, 5000);
break;
server中的實作, getQuestion function處理前端丟過來的 'getQuestion' 狀態,
GAME物件中有一個getQuestion的方法, 是我們真正取得當前題目的地方,
這邊最重要的地方是處理isPlayerOneReady和questionStep(第幾條題目)的狀態,
否則會產生兩位玩家題目不同步的問題,最後在沒有題目之後,送回'gameOver'的狀態
getQuestion (data) {
try {
console.log(`room: ${ data.id } asking question.`)
const GAME = gameRoomsList.filter((value) => {
return value.id === data.id
})[0].room;
let question = GAME.getQuestion();
if ( GAME.isPlayerOneReady ) {
GAME.isPlayerOneReady = false
GAME.questionStep += 1
}else {
GAME.isPlayerOneReady = true
}
let res = {
id : data.id
};
if ( question ) {
res.type = 'question'
res.question = question.question
res.optionA = question.optionA
res.optionB = question.optionB
}else {
res.type = 'gameOver'
}
connection.send(JSON.stringify(res))
} catch (error) {
connection.close()
throw error
}