這幾年 Node.js 在台灣許多網站都開始使用,我對這項技術一直頗有興趣,在想能怎麼使用這項技術去玩些有趣的互動。
曾照著網上熱心前輩所寫的文章試著寫寫看,也在去年九月參加了 HTML5與Node.js在台灣聯合技術小聚,但一時案子忙碌,實在沒有心力好好研究便停滯了。
最近公司上線的案子(1, 2)剛好能有這個機會讓我來玩玩,目的是讓使用者透過手機網頁來與電腦開啟的網頁做些即時互動。
用 App 寫要考量跨平台與門檻(還要去下載 App,應該會讓一些單純想玩玩 Event 的使用者卻步)的問題,因此便希望能都用 Web 上的技術來達成囉。
此篇便簡單紀錄一下 Node.js 在 FreeBSD 上的安裝,以及簡單製作一個手機與電腦即時互動的網頁。
自認觀念上還不是相當清楚便迫不及待分享了,若有誤之處還請前輩給予指導囉 :)
一、安裝
2013/05/13 更新:
近日有網友問到新版的寫法不同,照舊寫法會不通,於是我再更新版本試了,請參考看看囉。
我自家使用的伺服器環境是 FreeBSD,所以這邊就介紹在 FreeBSD 上安裝 Nodejs 的方法。
ports 裡面有喔!直接進去裝就可以了~真是方便!
root@patwbsd [/root] # cd /usr/ports/www/npm/
root@patwbsd [/usr/ports/www/npm] # make install clean
這邊會出現藍底畫面,請選擇勾選安裝 node-devel。
如果順利的話應該就可以安裝完畢,但有時候會遇到找不到相符版本的情況,那就這樣做吧:
# 看起來 work 裡面沒有最新版 v0.6.14 ... 好吧,自己去抓回來。
root@patwbsd [/usr/ports/www/node/work] # fetch http://nodejs.org/dist/v0.6.14/node-v0.6.14.tar.gz
node-v0.6.14.tar.gz 100% of 10MB 1838 kBps
# 解壓縮:
root@patwbsd [/usr/ports/www/node/work] # tar zxf node-v0.6.14.tar.gz
# 然後進去編譯:
root@patwbsd [/usr/ports/www/node/work] # cd node-v0.6.14
root@patwbsd [/usr/ports/www/node/work/node-v0.6.14] # ./configure
root@patwbsd [/usr/ports/www/node/work/node-v0.6.14] # gmake
# 再出來安裝:
root@patwbsd [/usr/ports/www/node/work] # cd ..
root@patwbsd [/usr/ports/www/node] # make install clean
經過一段時間的等待,終於安裝完了!
可以試一下能不能執行,印出 nodejs 的版本試試:
※小提醒:如果 FreeBSD 還沒認出 node,就 rehash 一下再執行。
root@patwbsd [/root ] # node -v
v0.10.4
安裝介紹至此終了。
接下來是第二單元,來實作囉!:D
二、實作:使用 Node.js 來達成電腦網頁與手機網頁即時互動
這邊會寫一個簡單的範例來展示怎麼用 Node.js 來達成電腦網頁與手機網頁即時互動。
首先,我們會用上 socket.io 跟 express 兩個套件,先裝好吧:
root@patwbsd [/home/ftp/patw/nodejs] # npm install socket.io
root@patwbsd [/home/ftp/patw/nodejs] # npm install express
裝完之後,應該可以在所在目錄底下看到 node_modules/ 目錄。
OK,準備完畢,開始寫吧。
我們可以將這隻 nodejs 程式命名為 server.js,先簡單寫些內容測試看看:
express 2.x 版本寫法:
// 引入 express & socket.io
var app = require('express').createServer()
var io = require('socket.io').listen(app);
// 偵聽在 8081 port,隨你喜歡
app.listen(8081);
console.log('Server running');
// Routing,其實這首頁沒什麼用
app.get('/', function (req, res) {
res.sendfile(__dirname + '/index.html');
});
express 3.x 版本寫法,請將前面改成:
var express = require('express'),
app = express(),
http = require('http'),
server = http.createServer(app),
io = require('socket.io').listen(server);
server.listen(8081);
存檔,再準備一個預設的 index.html 用來看看 Server 是否有 Run 起來吧。(照慣例打個 Hello world! 好了 :D)
Run run 看:
root@patwbsd [/home/ftp/patw/nodejs] # node server.js
info - socket.io started
Server running
順利的話應該可以看到執行後的兩行訊息,其中 Server running 是我們在程式中用 console.log 印出的。
然後連線到 http://你的ip:8081/ ,應該就可以看到剛剛我們所設定的 index.html 內容。
接著,我們要增加偵聽事件,讓 Nodejs Server 在接收到訊息後再發出動作,以達到互動的效果。
一樣是改 server.js 這支:
express 2.x 版本寫法:
var app = require('express').createServer()
var io = require('socket.io').listen(app);
app.listen(8081);
console.log('Server running');
app.get('/', function (req, res) {
res.sendfile(__dirname + '/index.html');
});
// 連線
io.sockets.on('connection', function (socket) {
// 偵聽 send 事件
socket.on('send', function (data) {
// 然後我們依據 data.act 做不同的動作
switch ( data.act )
{
// 這個是使用者打開手機網頁後發生的事件
case 'enter':
io.sockets.emit('get_response', data);
console.log('Sending getEnter');
break;
// 這個是使用者在手機網頁中點擊按鈕,讓電腦網頁背景變色的事件
case 'changebg';:
io.sockets.emit('get_response', data);
console.log('Sending changeBg');
break;
}
});
});
express 3.x 版本寫法,請將前面改成:
var express = require('express'),
app = express(),
http = require('http'),
server = http.createServer(app),
io = require('socket.io').listen(server);
server.listen(8081);
OK,存檔。一樣用 node server.js 讓它運行。
伺服器端的程式差不多了,再來是電腦網頁與手機網頁的撰寫囉。
要怎麼讓特定手機網頁能夠控制特定電腦網頁呢?思考方向是──設定一組專屬的 KEY,一對一,就可以知道只聽到某個 KEY 的手機網頁呼叫,電腦網頁才會動作。
為了讓手機使用者方便輸入,這邊將網址包含 KEY 變成一組 QRCode。 (使用 Google Charts)
流程大致是這樣:
使用者開啟電腦網頁→用手機掃描網頁上的 QRCode→手機打開了專屬 KEY 的網頁→電腦網頁透過 Nodejs 伺服器知道這個 KEY 被打開了→開始互動
電腦網頁的 code 如下:
<!document html>
<html>
<head>
<meta charset="utf-8">
<title>Nodejs - 電腦網頁</title>
<script src="https://ajax.googleapis.com/ajax/libs/jquery/1.7.2/jquery.min.js"></script>
<script src="http://Nodejs伺服器位置:埠號/socket.io/socket.io.js" type="text/javascript"></script>
<style type="text/css">
#main {
display: none;
}
</style>
<script type="text/javascript">
// 用來產生類似 GUID 的字串
function S4() {
return (((1+Math.random())*0x10000)|0).toString(16).substring(1);
}
function NewGuid() {
return (S4()+S4());
}
$(document).ready(function(){
var key = NewGuid();
console.log(key);
$("#qrcode").append("<img src='http://chart.apis.google.com/chart?chs=300x300&cht=qr&chl=http://手機版網址/?key=" + key + "&choe=UTF-8' />");
// NodeJS Server
var nodejs_server = "Nodejs伺服器位置:埠號";
// 進行 connect
var socket = io.connect("http://" + nodejs_server);
// 偵聽 nodejs 事件
socket.on("get_response", function (b) {
var combine = b.key + "_" + b.act;
console.log(combine);
switch (combine) {
// 當擁有特定 KEY 的使用者打開手機版網頁,觸發 enter 事件,就會將 qrcode 隱藏,並秀出一張圖
case key + "_enter":
setTimeout(function () {
$("#qrcode").hide();
$("#main").show();
}, 500);
break;
// 當擁有特定 KEY 的使用者在手機版網頁中,觸發 changebg 事件,就會將網頁的背景顏色隨機變換
case key + "_changebg":
setTimeout(function () {
var str = "0123456789abcdef", t = "";
for (j = 0; j < 6; j++) {
t = t + str.charAt(Math.random() * str.length);
}
$("body").css("background-color", t);
}, 500);
break;
}
});
});
</script>
</head>
<body>
<div id="qrcode"></div>
<div id="main"><img src="amber.jpg" /></div>
</body>
</html>
至於手機版網頁的 code 如下:(本例用 PHP 撰寫,目的是取得 querystring 的 key 值)
<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8" />
<title>Nodejs - 手機網頁</title>
<meta name="viewport" content="width=device-width, initial-scale=1.0, maximum-scale=1.0, user-scalable=0">
<meta name="author" content="patw, Patrick Wang" />
<script src="http://ajax.googleapis.com/ajax/libs/jquery/1.7.2/jquery.min.js"></script>
<script src="http://Nodejs伺服器位置:埠號/socket.io/socket.io.js" type="text/javascript"></script>
<script type="text/javascript">
$(document).ready(function() {
// ==========================================================================================================================
// 建立 Socket IO 連線
// ==========================================================================================================================
var socket = io.connect("http://Nodejs伺服器位置:埠號");
"undefined" != typeof console && console.log("user enter via mobile");
// ==========================================================================================================================
"undefined" != typeof console && console.log("enter mobile page");
socket.emit("send", {
key: "<?php echo $_GET['key'];?>",
act: "enter"
});
$("#change_btn").click(function(){
"undefined" != typeof console && console.log("send change color command");
socket.emit("send", {
key: "<?php echo $_GET['key'];?>",
act: "changebg"
});
});
});
</script>
</head>
<body>
<p>打開手機網頁成功!快看看你的電腦螢幕吧!</p>
<input id="change_btn" type="button" value="控制電腦端變背景色" />
</body>
</html>
最後放個成果的 DEMO 影片:
以上,與大家分享。
也希望有心得的朋友一起討論喔:D 看能做出什麼更有趣的東西
很棒的文章,謝謝!我真要自己給nodejs試試看。比如說我要做一個nodejs網站,你知道在哪裡找得到nodejs服務器呢?
謝謝 : )
我是自行架設的, 也許你可以看看支援的虛擬主機 ( http://wiki.nodejs.tw/nodejs_vps )
或是在這邊詢問看看還有什麼好用的服務器.
啊,heroku有nodejs服務,酷!現在我沒有藉口了…
這行會出錯,請問是甚麼原因?我的主機上也找不到 socker.io.js 這隻程式
語法被吃掉?
socket.io 要用 npm install 安裝喔。
hello 你好
我有試著照您的程式碼做可是弄不出來目前新的express3.x與socket.io寫法有些不同,我目前的問題在我的圖片顯示不出來,以及手機show出網頁後電腦端沒動作。
不知是哪裡有問題可以幫忙一下嗎?
Hi, 我剛更新了 express 3.x 部分的寫法, 測試本範例有成功喔, 請再試試看吧.
請問手機版網頁的程式碼要放在哪
手機版網頁一樣放在 Web Server 上哦!
請問手機版網頁是run在手機?
所以你的手機執行php嗎?
thx
手機版網頁一樣放在 Web Server 上哦!手機只是連到該頁面上瀏覽而已。
你好
最近在學習Node.js
很喜歡你的範例拿來練習
現在卡在手機無法連上
DNS查詢失敗
一直不知道改哪裡好
因此想請教你
謝謝
你是如何架設手機端網頁的呢?
咦 是php檔那頁嗎 我把他放在本機端 是要上到網路上嗎?
用本機當作 Server 也可以,不過手機要能連得上你的本機。
不懂耶….
不過已經將php檔改寫成js成功執行了
謝謝你
您好,我以本機run node.js,但是手機連不到本機的網頁,請問server.js 這個檔案是否有需要修改什麼設定嗎?
手機與本機在同一個網段底下嗎?是的話,使用內網 IP 能連上嗎?
最近也想在我的網站加入即時互動功能, 剛好搜尋到~謝謝分享