3. 《⼋八屏⼀一雲時代來臨 教你HTML5六⼩小時打通關 》
LICENSE NOTICE
This work is licensed under a Creative Commons Attribution-NoDerivs 3.0 Unported License.
You are free:
• to Share — to copy, distribute and transmit the work
• to make commercial use of the work
Under the following conditions:
• Attribution — You must attribute the work in the manner specified by the author or licensor (but not in any
way that suggests that they endorse you or your use of the work).
• No Derivative Works — You may not alter, transform, or build upon this work.
With the understanding that:
• Waiver — Any of the above conditions can be waived if you get permission from the copyright holder.
• Public Domain — Where the work or any of its elements is in the public domain under applicable law, that
status is in no way affected by the license.
• Other Rights — In no way are any of the following rights affected by the license:
◦ Your fair dealing or fair use rights, or other applicable copyright exceptions and limitations;
◦ The author's moral rights;
◦ Rights other persons may have either in the work itself or in how the work is used, such as publicity or
privacy rights.
• Notice — For any reuse or distribution, you must make clear to others the license terms of this work. The
best way to do this is with a link to this web page.
Copyright (C) 2013 Moko365 Inc. All Rights Reserved.
3
4. Data Push 架構設計
Copyright (C) 2013 Moko365 Inc. All Rights Reserved.
本教材由仕橙3G教室製作與維護 仕橙研策科技有限公司版權所有
4
6. 《⼋八屏⼀一雲時代來臨 教你HTML5六⼩小時打通關 》
基本功能
聊天室 (Chat)
通訊錄 (Contact)
圖⽚片傳送 (File Transfer)
Copyright (C) 2013 Moko365 Inc. All Rights Reserved.
6
7. 《⼋八屏⼀一雲時代來臨 教你HTML5六⼩小時打通關 》
基礎架構與建設
Feature Architect Infrastructure
聊天室 Real-time Data Push Device & Cloud
通訊錄 Database Device
圖片傳送 Real-time Data Push Device & Cloud
Copyright (C) 2013 Moko365 Inc. All Rights Reserved.
7
8. 《⼋八屏⼀一雲時代來臨 教你HTML5六⼩小時打通關 》
Device/Cloud Interactive
Data Pull
Data Push
Asynchronous Data Pull
Copyright (C) 2013 Moko365 Inc. All Rights Reserved.
8
9. 《⼋八屏⼀一雲時代來臨 教你HTML5六⼩小時打通關 》
Data Pull
Client Server
Synchronous
Return
Copyright (C) 2013 Moko365 Inc. All Rights Reserved.
9
11. 《⼋八屏⼀一雲時代來臨 教你HTML5六⼩小時打通關 》
Data Push
Client Server
Create WebSocket
Return
Data
Copyright (C) 2013 Moko365 Inc. All Rights Reserved.
11
12. 《⼋八屏⼀一雲時代來臨 教你HTML5六⼩小時打通關 》
Data Push using WebSocket (HTML5)
Client Server
Create WebSocket
onopen()
onmessage()
Copyright (C) 2013 Moko365 Inc. All Rights Reserved.
12
13. 《⼋八屏⼀一雲時代來臨 教你HTML5六⼩小時打通關 》
WebSocket 與 HTTP API
HTML5
HTTP API
Browser
WebSocket
Native
Socket (TCP/IP)
Copyright (C) 2013 Moko365 Inc. All Rights Reserved.
13
14. 《⼋八屏⼀一雲時代來臨 教你HTML5六⼩小時打通關 》
HTTP API 與 WebSocket 是主流
Application Layer Language Technology
HTML5 Front-end HTML HTTP API
Browser JavaScript WebSocket
Native Apps C/C++/Java Socket
Copyright (C) 2013 Moko365 Inc. All Rights Reserved.
14
15. 《⼋八屏⼀一雲時代來臨 教你HTML5六⼩小時打通關 》
HTTP API
The HTTP Server API enables applications to communicate
over HTTP.
Servers will receive HTTP requests, and send HTTP responses.
With SSL support.
In the form of URL, one of the format of URI.
Copyright (C) 2013 Moko365 Inc. All Rights Reserved.
15
16. 《⼋八屏⼀一雲時代來臨 教你HTML5六⼩小時打通關 》
HTTP API 的形式
API Query string
http://localhost:8888/send?m=hello&u=jollen
Copyright (C) 2013 Moko365 Inc. All Rights Reserved.
16
17. 《⼋八屏⼀一雲時代來臨 教你HTML5六⼩小時打通關 》
HTTP API 的格式
API Query string
http://localhost:8888/send?m=hello&u=jollen
Pathname URL
Copyright (C) 2013 Moko365 Inc. All Rights Reserved.
17
18. 《⼋八屏⼀一雲時代來臨 教你HTML5六⼩小時打通關 》
Client Requests
GET /index.html HTTP/1.1
Host: www.moko365.com
Copyright (C) 2013 Moko365 Inc. All Rights Reserved.
18
19. 《⼋八屏⼀一雲時代來臨 教你HTML5六⼩小時打通關 》
Server Responses
HTTP/1.1 200 OK
Date: Sun, 10 June 2012 00:00:00 GMT
Server: Apache/1.3.3.7 (Unix) (Red-Hat/Linux)
Last-Modified: Fri, 01 June 2012 22:11:55 GMT
Etag: "3481d-2c6-7d1ab33e"
Accept-Ranges: none
Content-Length: 568
Connection: close
Content-Type: text/html; charset=UTF-8
...
Copyright (C) 2013 Moko365 Inc. All Rights Reserved.
19
20. 《⼋八屏⼀一雲時代來臨 教你HTML5六⼩小時打通關 》
Response Content
HTML Document
XML Document
JSON Data
Base64 encode (⽤用於 Binary 檔案)
亦可⾃自定
Copyright (C) 2013 Moko365 Inc. All Rights Reserved.
20
21. 《⼋八屏⼀一雲時代來臨 教你HTML5六⼩小時打通關 》
Open API 定義
Open API is over HTTP:
➡ http://svn.moko365.com:8888/start,連接伺服器並接收即時訊息
➡ http://svn.moko365.com:8888/send,送出⽂文字訊息
API 參數 (Query String) 的部份後續再做定義
以 JSON 格式打包回傳資料
Copyright (C) 2013 Moko365 Inc. All Rights Reserved.
21
22. 《⼋八屏⼀一雲時代來臨 教你HTML5六⼩小時打通關 》
Apache with NodeJS
index.html
Apache
(Document)
WebSocket
Connection
NodeJS
Data
(Application)
Push
APIs Platform
http://svn.moko365.com:8080/send
http://svn.moko365.com:8080/start
Copyright (C) 2013 Moko365 Inc. All Rights Reserved.
22
23. 使用 JSON
Copyright (C) 2013 Moko365 Inc. All Rights Reserved.
本教材由仕橙3G教室製作與維護 仕橙研策科技有限公司版權所有
23
24. 《⼋八屏⼀一雲時代來臨 教你HTML5六⼩小時打通關 》
JSON 簡介
JSON (play /ˈdʒeɪsən/), or
JavaScript Object Notation
a lightweight text-based open standard designed
for human-readable data interchange.
It is derived from the JavaScript scripting language
for representing simple data structures and
associative arrays, called objects.
Despite its relationship to JavaScript, it is language-
independent, with parsers available for many
languages.
Source: http://en.wikipedia.org/wiki/JSON
Copyright (C) 2013 Moko365 Inc. All Rights Reserved.
24
25. 《⼋八屏⼀一雲時代來臨 教你HTML5六⼩小時打通關 》
Basic Types
Number (type not specified, but in practice double precision floating-
point format, as this is how JavaScript in Web browsers treats it)
String (double-quoted Unicode (UTF-8 by default), with backslash
escaping)
Boolean (true or false)
Array (an ordered sequence of values, comma-separated and enclosed
in square brackets; the values do not need to be of the same type)
Object (an unordered collection of key:value pairs with the ':' character
separating the key and the value, comma-separated and enclosed in
curly braces; the keys must be strings and should be distinct from each
other)
null (empty)
Copyright (C) 2013 Moko365 Inc. All Rights Reserved.
25
26. 《⼋八屏⼀一雲時代來臨 教你HTML5六⼩小時打通關 》
Schema
Array (an ordered sequence of values, comma-
separated and enclosed in square brackets; the values
do not need to be of the same type)
Array
var o = [ 100, 500, 300, 200, 400 ]
Copyright (C) 2013 Moko365 Inc. All Rights Reserved.
26
27. 《⼋八屏⼀一雲時代來臨 教你HTML5六⼩小時打通關 》
Schema
Object (an unordered collection of key:value pairs with
the ':' character separating the key and the value, comma-
separated and enclosed in curly braces; the keys must be
strings and should be distinct from each other)
var o = { Single Row
height: 100,
width: 500, Object
}
Copyright (C) 2013 Moko365 Inc. All Rights Reserved.
27
28. 《⼋八屏⼀一雲時代來臨 教你HTML5六⼩小時打通關 》
Example 1
[
! {
! ! color: "red",
! ! value: "#f00" color value
! },
! {
! ! color: "green", red #f00
! ! value: "#0f0"
! },
! { green #0f0
! ! color: "blue",
! ! value: "#00f"
! }, blue #00f
! {
! ! color: "cyan", cyan #0ff
! ! value: "#0ff"
! }
]
Copyright (C) 2013 Moko365 Inc. All Rights Reserved.
28
33. 《⼋八屏⼀一雲時代來臨 教你HTML5六⼩小時打通關 》
JSON Stringify and Parse
var o = [ 15 ]; // Array (type)
var o = "[ 15 ]"; // string
[ 15 ] --> "[ 15 ]" // Stringify: JSON.stringify()
“[ 15 ]” --> [ 15 ] // Parse: JSON.parse()
Copyright (C) 2013 Moko365 Inc. All Rights Reserved.
33
34. 《⼋八屏⼀一雲時代來臨 教你HTML5六⼩小時打通關 》
Platform: Open API
API: Get prefetch list
➡ http://singletoapp.com/jollen-php-json
Return (JSON):”
➡ “url”: The prefetch URL
➡ “expires”: Document expire
➡ “tag”: Keywords
Copyright (C) 2013 Moko365 Inc. All Rights Reserved.
34
35. 《⼋八屏⼀一雲時代來臨 教你HTML5六⼩小時打通關 》
JavaScript 解析 JSON
使⽤用 json.js (json2.js)
➡ http://www.JSON.org/js.html
Open source JSON parser for JavaScript
Copyright (C) 2013 Moko365 Inc. All Rights Reserved.
35
36. 《⼋八屏⼀一雲時代來臨 教你HTML5六⼩小時打通關 》
JSON+jQuery Tmpl
MVC
➡ Model: Server
➡ View: Device (Client)
➡ Control: Server
Copyright (C) 2013 Moko365 Inc. All Rights Reserved.
36
37. 《⼋八屏⼀一雲時代來臨 教你HTML5六⼩小時打通關 》
範例
<html>
<head>
<title>Parsing Message using JSON in JavaScript</title>
<script language="javascript" src="json.js"></script>
<script language="javascript" >
var students = {
"ClassA" : [
! { "name": "jollen", "age": “30”, "address": "Unknown"},
! { "name": "Paul", "age": “30”, "address": "Unknown"},
! { "name": "Peter", "age": “30”, "address": "Unknown"}
! ]
}
var i = 0
var arrayObject = new Array();
for(i = 0;i < students.ClassA.length; i++)
{
arrayObject.push(students.ClassA[i].name);
arrayObject.push(students.ClassA[i].age);
arrayObject.push(students.ClassA[i].address);
}
alert("Parsing JSON Message Example ");
alert(arrayObject.toJSONString().parseJSON());
</script>
</head>
<body>
Parsing Message using JSON in JavaScript
</body>
</html>
Copyright (C) 2013 Moko365 Inc. All Rights Reserved.
37
38. 《⼋八屏⼀一雲時代來臨 教你HTML5六⼩小時打通關 》
Javascript 與 JSON 實例
使⽤用 Javascript 解析 JSON
➡ JSON 的優點在此完全展現
搭配 jquery.tmpl.js 使⽤用
➡ https://github.com/jquery/jquery-tmpl
JSON
<script>
var movies = [
{ Name: "Meet Joe Black", Languages: ["French"] },
{ Name: "The Mighty", Languages: [] },
{ Name: "City Hunter", Languages: ["Mandarin", "Cantonese"] }
];
/* Render the template with the movies data */
$( "#movieTemplate" ).tmpl( movies )
.appendTo( "#movieList" );
</script>
Copyright (C) 2013 Moko365 Inc. All Rights Reserved.
38
42. 《⼋八屏⼀一雲時代來臨 教你HTML5六⼩小時打通關 》
JSON 的未來性
第⼀一代 Browser
➡ HTML Browser
➡ All from Internet
第⼆二代 Browser
➡ JSON Browser
➡ Local: HTML5 Tempalte/CSS3/JavaScript Library
➡ Data in JSON format comes from Server side
Copyright (C) 2013 Moko365 Inc. All Rights Reserved.
42
43. 使用 HTML5 的 WebSocket
Copyright (C) 2013 Moko365 Inc. All Rights Reserved.
本教材由仕橙3G教室製作與維護 仕橙研策科技有限公司版權所有
43
44. 《⼋八屏⼀一雲時代來臨 教你HTML5六⼩小時打通關 》
關於 “WebSocket” 物件
注意瀏覽器的⽀支援性
使⽤用 DOM 的 “WebSocket” 物件
採⽤用 JavaScript 撰寫程式碼
推薦的⼊入⾨門⽂文章
➡ http://www.html5rocks.com/en/tutorials/websockets/basics/
➡ https://developer.mozilla.org/en-US/docs/WebSockets
Copyright (C) 2013 Moko365 Inc. All Rights Reserved.
44
45. 《⼋八屏⼀一雲時代來臨 教你HTML5六⼩小時打通關 》
第⼀一次寫 WebSocket
8 <script type="text/javascript">
9 function WebSocketTest()
10 {
11 if ("WebSocket" in window)
12 {
13 // Let us open a web socket
14 var ws = new WebSocket("ws://svn.moko365.com:8080/", "echo-
protocol");
15 ws.onopen = function(evt)
16 {
17 alert("open");
18 };
19 ws.onclose = function(evt)
20 {
21 alert("close");
22 };
23 }
24 else
25 {
26 // The browser doesn't support WebSocket
27 alert("WebSocket NOT supported by your Browser!");
28 }
29 }
30 </script>
Copyright (C) 2013 Moko365 Inc. All Rights Reserved.
45
46. 《⼋八屏⼀一雲時代來臨 教你HTML5六⼩小時打通關 》
WebSocket:瀏覽器的⽀支援性
請參考 http://en.wikipedia.org/wiki/WebSocket
Copyright (C) 2013 Moko365 Inc. All Rights Reserved.
46
47. 《⼋八屏⼀一雲時代來臨 教你HTML5六⼩小時打通關 》
主要瀏覽器的 WebSocket ⽀支援
Firefox 6 以後
Google Chrome 14 以後
Internet Explorer 10 Developer Preview 以後
Opera 11 以後⽀支援舊版 WebSocket 實作
Safari 5 以後⽀支援舊版 WebSocket 實作
iOS 4.2 以後⽀支援舊版 WebSocket 實作
Android 4.x 內建瀏覽器不⽀支援 WebSocket
Copyright (C) 2013 Moko365 Inc. All Rights Reserved.
47
48. NodeJS 與 Open API
Copyright (C) 2013 Moko365 Inc. All Rights Reserved.
本教材由仕橙3G教室製作與維護 仕橙研策科技有限公司版權所有
48
50. 《⼋八屏⼀一雲時代來臨 教你HTML5六⼩小時打通關 》
hello.js
var http = require('http');
http.createServer(function (req, res) {
res.writeHead(200, {'Content-Type': 'text/html'});
res.end('<h1>Hello World</h1>n');
}).listen(1234, '127.0.0.1');
console.log('Server running at http://127.0.0.1:1234/');
Copyright (C) 2013 Moko365 Inc. All Rights Reserved.
50
51. 《⼋八屏⼀一雲時代來臨 教你HTML5六⼩小時打通關 》
執⾏行 hello.js
% node hello.js
Server running at http://127.0.0.1:1234/
Copyright (C) 2013 Moko365 Inc. All Rights Reserved.
51
52. 《⼋八屏⼀一雲時代來臨 教你HTML5六⼩小時打通關 》
NodeJS 的 HTTP APIs
var http = require('http');
http.createServer(function (req, res) {
res.writeHead(200, {'Content-Type': 'text/html'});
res.end('<h1>Hello World</h1>n');
}).listen(1234, '127.0.0.1');
console.log('Server running at http://127.0.0.1:1234/');
http.createServer([requestListener])
Copyright (C) 2013 Moko365 Inc. All Rights Reserved.
52
53. 《⼋八屏⼀一雲時代來臨 教你HTML5六⼩小時打通關 》
requestListener
var http = require('http');
http.createServer(function (req, res) {
res.writeHead(200, {'Content-Type': 'text/html'});
res.end('<h1>Hello World</h1>n');
}).listen(1234, '127.0.0.1');
console.log('Server running at http://127.0.0.1:1234/');
function (request, response) { }
Copyright (C) 2013 Moko365 Inc. All Rights Reserved.
53
54. 《⼋八屏⼀一雲時代來臨 教你HTML5六⼩小時打通關 》
HTTP Headers
var http = require('http');
http.createServer(function (req, res) {
res.writeHead(200, {'Content-Type': 'text/html'});
res.end('<h1>Hello World</h1>n');
}).listen(1234, '127.0.0.1');
console.log('Server running at http://127.0.0.1:1234/');
{ 'content-length': '123',
'content-type': 'text/plain',
'connection': 'keep-alive',
'accept': '*/*' }
Copyright (C) 2013 Moko365 Inc. All Rights Reserved.
54
55. 《⼋八屏⼀一雲時代來臨 教你HTML5六⼩小時打通關 》
HTTP Headers
var http = require('http');
http.createServer(function (req, res) {
res.writeHead(200, {'Content-Type': 'text/html'});
res.end('<h1>Hello World</h1>n');
}).listen(1234, '127.0.0.1');
console.log('Server running at http://127.0.0.1:1234/');
server.listen(port, [hostname], [callback])
Copyright (C) 2013 Moko365 Inc. All Rights Reserved.
55
56. 《⼋八屏⼀一雲時代來臨 教你HTML5六⼩小時打通關 》
Server Push
Server Push 的重要性遠勝於 Client Pull
➡ Real-Time Web Application
使⽤用 NodeJs + Web Socket
Web Socket 是 HTML5 的新技術
Copyright (C) 2013 Moko365 Inc. All Rights Reserved.
56
57. 《⼋八屏⼀一雲時代來臨 教你HTML5六⼩小時打通關 》
Web Socket 的⽤用途
Web 的 Socket
Client 建⽴立⼀一個連線通道 (Socket) 到 Web Server
“using NodeJS will push the notification to the clients which
are connected to this server through Web Socket”
Copyright (C) 2013 Moko365 Inc. All Rights Reserved.
57
58. 《⼋八屏⼀一雲時代來臨 教你HTML5六⼩小時打通關 》
Push Server
Client 與 Server 端的實作
Client:
➡ HTML5 App (⼿手機端)
➡ 建⽴立 WebSocket 到 Server
Server:
➡ Server 以 JSON 推送資料給 Client
➡ 不使⽤用 Apache Server、改⽤用 NodeJS Server
➡ NodeJS 可搭配 Apache+PHP
Copyright (C) 2013 Moko365 Inc. All Rights Reserved.
58
59. 《⼋八屏⼀一雲時代來臨 教你HTML5六⼩小時打通關 》
Client: 建⽴立 WebSocket 連線
var trigger = "updateContent";
$(document).ready(function(){
host = "localhost:8000";
conn = new WebSocket("ws://"+host+"/");
conn.onmessage = function(evt) {
// Make an Ajax call to the server to update the content
if (evt.data == "update"){
// Call the trigger function when there is an update
window[trigger]();
}
};
conn.onerror = function() {
};
conn.onclose = function() {
conn = false;
};
conn.onopen = function() {
// alert("You are connected");
postMessage("You are connected");
};
}
Copyright (C) 2013 Moko365 Inc. All Rights Reserved.
59
60. 《⼋八屏⼀一雲時代來臨 教你HTML5六⼩小時打通關 》
Server: 啟動並監聽 WebSocket
var server = ws.createServer({
server: httpServer
});
server.addListener("listening", function(){
sys.log("Listening for connections.");
});
// Handle WebSocket Requests
server.addListener("connection", function(conn){
console.log('[*] open');
conn.addListener("message", function(message){
if (message == 'close') {
console.log('[-] close requested')
conn.close();
} else {
console.log('[+] ', (new Buffer(message)).inspect());
server.broadcast("update");
}
});
conn.addListener("close", function(){
console.log('[*] close');
})
});
server.addListener("disconnect", function(conn){ });
server.listen(8000);
Copyright (C) 2013 Moko365 Inc. All Rights Reserved.
60
61. 《⼋八屏⼀一雲時代來臨 教你HTML5六⼩小時打通關 》
Routers
url.parse(string).pathname url.parse(string).query
http://localhost:8888/start?u=android&m=moko365
querystring(string)["u"]
querystring(string)["m"]
Copyright (C) 2013 Moko365 Inc. All Rights Reserved.
61
62. 《⼋八屏⼀一雲時代來臨 教你HTML5六⼩小時打通關 》
start.js
var http = require("http");
var url = require("url");
function start() {
function onRequest(request, response) {
var pathname = url.parse(request.url).pathname;
console.log("Request for " + pathname + " received.");
response.writeHead(200, {"Content-Type": "text/plain"});
response.write("Hello World");
response.end();
}
http.createServer(onRequest).listen(8888);
console.log("Server has started.");
}
exports.start = start;
Copyright (C) 2013 Moko365 Inc. All Rights Reserved.
62
63. 《⼋八屏⼀一雲時代來臨 教你HTML5六⼩小時打通關 》
route.js
function route(pathname) {
console.log("About to route a request for " + pathname);
}
exports.route = route;
Copyright (C) 2013 Moko365 Inc. All Rights Reserved.
63
64. 《⼋八屏⼀一雲時代來臨 教你HTML5六⼩小時打通關 》
Revision 2 of start.js
var http = require("http");
var url = require("url");
function start(route) {
function onRequest(request, response) {
var pathname = url.parse(request.url).pathname;
console.log("Request for " + pathname + " received.");
route(pathname);
response.writeHead(200, {"Content-Type": "text/plain"});
response.write("Hello World");
response.end();
}
http.createServer(onRequest).listen(8888);
console.log("Server has started.");
}
exports.start = start;
Copyright (C) 2013 Moko365 Inc. All Rights Reserved.
64
65. 《⼋八屏⼀一雲時代來臨 教你HTML5六⼩小時打通關 》
index.js
var server = require("./server");
var router = require("./router");
server.start(router.route);
$ node index.js
Copyright (C) 2013 Moko365 Inc. All Rights Reserved.
65
66. 《⼋八屏⼀一雲時代來臨 教你HTML5六⼩小時打通關 》
使⽤用 Request Handler
var server = require("./server");
var router = require("./router");
var requestHandlers = require("./requestHandlers");
var handle = {}
handle["/"] = requestHandlers.start;
handle["/start"] = requestHandlers.start;
server.start(router.route, handle);
Copyright (C) 2013 Moko365 Inc. All Rights Reserved.
66
67. 《⼋八屏⼀一雲時代來臨 教你HTML5六⼩小時打通關 》
Revision 3 of start.js
var http = require("http");
var url = require("url");
function start(router, handle) {
function onRequest(request, response) {
var pathname = url.parse(request.url).pathname;
console.log("Request for " + pathname + " received.");
route(handle, pathname);
response.writeHead(200, {"Content-Type": "text/plain"});
response.write("Hello World");
response.end();
}
http.createServer(onRequest).listen(8888);
console.log("Server has started.");
}
exports.start = start;
Copyright (C) 2013 Moko365 Inc. All Rights Reserved.
67
68. 《⼋八屏⼀一雲時代來臨 教你HTML5六⼩小時打通關 》
Revision 2 of route.js
function route(handle, pathname) {
console.log("About to route a request for " + pathname);
if (typeof handle[pathname] === 'function') {
handle[pathname]();
} else {
console.log("No request handler found for " + pathname);
}
}
exports.route = route;
Copyright (C) 2013 Moko365 Inc. All Rights Reserved.
68
69. 《⼋八屏⼀一雲時代來臨 教你HTML5六⼩小時打通關 》
Revision 3 of route.js
function route(handle, pathname) {
console.log("About to route a request for " + pathname);
if (typeof handle[pathname] === 'function') {
return handle[pathname]();
} else {
console.log("No request handler found for " + pathname);
return “Not found”;
}
}
exports.route = route;
Copyright (C) 2013 Moko365 Inc. All Rights Reserved.
69
70. 《⼋八屏⼀一雲時代來臨 教你HTML5六⼩小時打通關 》
Revision 4 of start.js
var http = require("http");
var url = require("url");
function start(router, handle) {
function onRequest(request, response) {
var pathname = url.parse(request.url).pathname;
console.log("Request for " + pathname + " received.");
response.writeHead(200, {"Content-Type": "text/plain"});
var respond = route(handle, pathname);
response.write(respond);
response.end();
}
http.createServer(onRequest).listen(8888);
console.log("Server has started.");
}
exports.start = start;
Copyright (C) 2013 Moko365 Inc. All Rights Reserved.
70
71. 《⼋八屏⼀一雲時代來臨 教你HTML5六⼩小時打通關 》
進階 NodeJS 技術
Non-blocking requests
Node.js process
Spawn child process
Proxying Node.js
Protocol parser
Advanced I/O handling
技術發展性
➡ Native service /daemon/ server -> Nodejs
➡ Hardware service is web service
Copyright (C) 2013 Moko365 Inc. All Rights Reserved.
71
72. Device & Cloud 整合
Copyright (C) 2013 Moko365 Inc. All Rights Reserved.
本教材由仕橙3G教室製作與維護 仕橙研策科技有限公司版權所有
72
73. 《⼋八屏⼀一雲時代來臨 教你HTML5六⼩小時打通關 》
⼿手機聊天:Device Side
<!DOCTYPE html>
<head>
<script type='text/javascript' src="./json2.js"></script>
<script type='text/javascript' src="./jquery.min.js"></script>
<script type='text/javascript' src="./jquery.websocket.js?v=0.2.2"></script>
</head>
<body>
<div id="message"></div> DOM is built on full filename
<div id="admin">
<form method="GET" action="http://svn.moko365.com:8080/send">
<input type="hidden" name="u" value="jollen" />
<input id="msg" type="text" name="m" value="Input message" />
<button type="submit" id="send">Send</button>
</form>
</div>
<script type="text/javascript">
$("#message").createWebSocket();
</script>
</body>
</html>
Copyright (C) 2013 Moko365 Inc. All Rights Reserved.
73
77. 《⼋八屏⼀一雲時代來臨 教你HTML5六⼩小時打通關 》
NodeJS 如何處理 Query String
var querystring = require('querystring');
/**
* Global variables
*/
var history = [ ];
function send(response, query, clients) {
console.log("Handler 'send' is started.");
console.log("Query string is: " + query);
var parsedstring = querystring.parse(query);
var obj = {
message: parsedstring.m,
username: parsedstring.u,
timestamp: (new Date()).getTime()
};
history.push(obj);
}
Copyright (C) 2013 Moko365 Inc. All Rights Reserved.
77
78. 《⼋八屏⼀一雲時代來臨 教你HTML5六⼩小時打通關 》
細說 createServer()
第3⾏行
➡ 呼叫http模組的createServer()函數來建⽴立⼀一個Web server
➡ reateServer()執⾏行成功後傳回Web server物件
➡ 參數requestListener是⼀一個Request function,⽤用來處理request事件
1 var http = require('http');
2
3 var httpServer = http.createServer(function (req, res) {
4 res.writeHead(200, {'Content-Type': 'text/html'});
5 res.end('<h1>Hello World</h1>n');
6 });
7
8 httpServer.listen(1234, '127.0.0.1');
9
10 console.log('Server running at http://127.0.0.1:1234/');
Copyright (C) 2013 Moko365 Inc. All Rights Reserved.
78
79. 《⼋八屏⼀一雲時代來臨 教你HTML5六⼩小時打通關 》
Request Callback
當request事件發⽣生時,Request function將被Callback
➡ req:http.ServerRequest的實例化(instance)
➡ res:http.ServerResponse的實例化
Copyright (C) 2013 Moko365 Inc. All Rights Reserved.
79
80. 《⼋八屏⼀一雲時代來臨 教你HTML5六⼩小時打通關 》
NodeJS 模組化
JavaScript⽐比較講求模組化
將Web server的部份獨⽴立成⼀一個模組
➡ index.js:主程式
➡ server.js:啟動Web server的模組
Copyright (C) 2013 Moko365 Inc. All Rights Reserved.
80
81. 《⼋八屏⼀一雲時代來臨 教你HTML5六⼩小時打通關 》
File: server.js
只能匯出函數
1 var http = require("http");
2
3 function start() {
4 function onRequest(request, response) {
5 console.log("Request for " + pathname + " received.");
6
7 response.writeHead(200, {"Content-Type": "text/plain"});
8 response.write("Hello World");
9 response.end();
10 }
11
12 http.createServer(onRequest).listen(8888);
13 console.log("Server has started.");
14 }
15
16 // Export functions
17 exports.start = start;
Copyright (C) 2013 Moko365 Inc. All Rights Reserved.
81
82. 《⼋八屏⼀一雲時代來臨 教你HTML5六⼩小時打通關 》
NodeJS 模組的觀念
並不需要將函數寫成模組
Client-side與Server-side都能⽤用JavaScript語⾔言開發軟體,沒想到
觀念與設計模組並不同,並無法完全相通
exports是NodeJS的⼀一個Global object(但並不完全是),⽤用途就是
匯出該模組裡的函數。
Copyright (C) 2013 Moko365 Inc. All Rights Reserved.
82
83. 《⼋八屏⼀一雲時代來臨 教你HTML5六⼩小時打通關 》
Callback Functions
NodeJS的事件處理機制,採⽤用典型的Callback functions(回呼函數)
做法
Copyright (C) 2013 Moko365 Inc. All Rights Reserved.
83
84. 《⼋八屏⼀一雲時代來臨 教你HTML5六⼩小時打通關 》
Routing
處理URL(HTTP Request)與Query string的核⼼心觀念
Client-side的JavaScript不太會使⽤用Route的觀念,這是Server-
side JavaScript的必殺技之⼀一
主要⽤用途是處理URL,所以我們利⽤用url模組來取出URL裡的
pathname,並將pathname交給route()函數
Copyright (C) 2013 Moko365 Inc. All Rights Reserved.
84
85. 《⼋八屏⼀一雲時代來臨 教你HTML5六⼩小時打通關 》
File: server.js
1 var http = require("http");
2 var url = require("url");
3
4 function start(route) {
5 function onRequest(request, response) {
6 var pathname = url.parse(request.url).pathname;
7 console.log("Request for " + pathname + " received.");
8 console.log("Request url: " + request.url);
9
10 route(pathname);
11
12 response.writeHead(200, {"Content-Type": "text/plain"});
13 response.write("Hello World");
14 response.end();
15 }
16
17 http.createServer(onRequest).listen(8888);
18 console.log("Server has started.");
19 }
20
21 // Export functions
22 exports.start = start;
Copyright (C) 2013 Moko365 Inc. All Rights Reserved.
85
86. 《⼋八屏⼀一雲時代來臨 教你HTML5六⼩小時打通關 》
函數即物件
函數就是物件
把route物件交給start()函數,讓start()函數去使⽤用物件
直接在start()裡呼叫route()函數也可以,為什麼不這樣做?
因為這不是JavaScript的觀念,倒是有點像是標準C語⾔言呼叫函數的
觀念,同時也會降低程式碼的可維護性
Copyright (C) 2013 Moko365 Inc. All Rights Reserved.
86
87. 《⼋八屏⼀一雲時代來臨 教你HTML5六⼩小時打通關 》
Request Handler
File: index.js
1 var server = require("./server");
2 var router = require("./router");
3 var handlers = require("./requestHandlers");
4
5 // 使⽤用 Object 來對應 pathname 與 request handlers
6 var handlers = {
7 "/": handlers.start,
8 "/start": handlers.start,
9 "/send": handlers.send
10 };
11
12 // 傳遞 request handler
13 server.start(router.route, handlers);
Copyright (C) 2013 Moko365 Inc. All Rights Reserved.
87
88. 《⼋八屏⼀一雲時代來臨 教你HTML5六⼩小時打通關 》
cont...
模組匯出start()與send()函數
分別處理相對應的pathname
主程式在第6⾏行到第10⾏行的地⽅方,利⽤用handlers物件來對應這個關係
呼叫start()時,再將handlers物件傳⼊入
Copyright (C) 2013 Moko365 Inc. All Rights Reserved.
88
89. 《⼋八屏⼀一雲時代來臨 教你HTML5六⼩小時打通關 》
再探 JavaScript 物件模型
JavaScript雖然不是物件導向式語⾔言,但仍要以物件的觀念來撰寫
將handlers以var定義成object
很多時候,或許也能以associative array來實作,但並不是很建議
Copyright (C) 2013 Moko365 Inc. All Rights Reserved.
89
90. 《⼋八屏⼀一雲時代來臨 教你HTML5六⼩小時打通關 》
HTTP API
許多Developer Platform,像是:Google API、Facebook API等,
提供了許多好⽤用的API供開發者使⽤用
基於HTTP的API將是HTML5應⽤用開發的核⼼心技術。
呼叫HTTP API的⽅方式,可使⽤用GET與POST⼆二種⽅方式,這⼆二種⽅方式都
是定義在HTTP裡的標準
⽤用⼾戶端(Caller)是瀏覽器
以Android的WebView組件,來製作與NodeJS整合的應⽤用程式
Copyright (C) 2013 Moko365 Inc. All Rights Reserved.
90
91. 《⼋八屏⼀一雲時代來臨 教你HTML5六⼩小時打通關 》
Open API 定義
Open API is over HTTP:
➡ http://svn.moko365.com:8888/start,連接伺服器並接收即時訊息
➡ http://svn.moko365.com:8888/send,送出⽂文字訊息
分別要處理⼆二個pathname如下:
➡ /start,由start() Handler處理
➡ /send,由send() Handler處理
Copyright (C) 2013 Moko365 Inc. All Rights Reserved.
91
92. 《⼋八屏⼀一雲時代來臨 教你HTML5六⼩小時打通關 》
Open API 參數說明
/start,建⽴立與Client的WebSocket連線。Query string的參數:
➡ username,使⽤用者名稱
/send,送出訊息。Query string的參數:
➡ m,訊息主體
➡ u,username
➡ to,對某⼈人說話
Copyright (C) 2013 Moko365 Inc. All Rights Reserved.
92
93. 《⼋八屏⼀一雲時代來臨 教你HTML5六⼩小時打通關 》
回傳的 JSON Data
{
! "type":"message",
! "data":!
{
! ! "message":"jollen",
! ! "username":"jollen",
! ! "timestamp":1351050127283
! ! }
}
Copyright (C) 2013 Moko365 Inc. All Rights Reserved.
93
94. 《⼋八屏⼀一雲時代來臨 教你HTML5六⼩小時打通關 》
⼀一個 Use Case
1. 使⽤用者點擊ItsApp,應⽤用程式⾃自動連線到http://
itsapp.moko365.com/api/start?username=jollen
2. Server建⽴立與⼿手機的WebSocket連線
3. 使⽤用者進⼊入主畫⾯面,使⽤用者可輸⼊入訊息;並且,可透過
WebSocket即時更新訊息
4. 使⽤用者輸⼊入訊息,並呼叫API:http://itsapp.moko365.com/
send?m=hello
5. 伺服器收到⽤用⼾戶端訊息,透過WebSocket將訊息Push給所有的⽤用
⼾戶端
Copyright (C) 2013 Moko365 Inc. All Rights Reserved.
94
95. 《⼋八屏⼀一雲時代來臨 教你HTML5六⼩小時打通關 》
解析 Query String
瀏覽器呼叫伺服器所提供的API,所以,現在的關鍵是如何解析
Query string
先將”querystring”程式庫匯⼊入,並呼叫parse()函數:
➡ var querystring = require('querystring');
➡ var parsedstring = querystring.parse(“m=helll&u=jollen”);
Copyright (C) 2013 Moko365 Inc. All Rights Reserved.
95
96. 《⼋八屏⼀一雲時代來臨 教你HTML5六⼩小時打通關 》
儲存結果
解析後的結果存放於parsedstring物件
➡ { m: 'hello', u: 'jollen' }
Copyright (C) 2013 Moko365 Inc. All Rights Reserved.
96
97. 《⼋八屏⼀一雲時代來臨 教你HTML5六⼩小時打通關 》
修改 requestHandler.js
13 function send(response, query) {
14 console.log("Handler 'send' is started.");
15 console.log("Query string is: " + query);
16
17 var parsedstring = querystring.parse(query);
18
19 var obj = {
20 message: parsedstring.m,
21 username: parsedstring.u,
22 timestamp: (new Date()).getTime()
23 };
24
25 history.push(obj);
26
27 //////// DEBUG ////////
28 for (var i = 0; i < history.length; i++) {
29 console.log("["+i+"]: " + history[i].message);
30 }
31 }
Copyright (C) 2013 Moko365 Inc. All Rights Reserved.
97
98. 《⼋八屏⼀一雲時代來臨 教你HTML5六⼩小時打通關 》
cont...
利⽤用了⼀一個全域陣列history來儲存訊息
將收到的訊息封裝成物件後, 再使⽤用標準的陣列操作將物件放到陣
列裡
將⼀一個時間記號(Timestamp)⼀一併封裝⾄至該物件裡
Copyright (C) 2013 Moko365 Inc. All Rights Reserved.
98
99. 《⼋八屏⼀一雲時代來臨 教你HTML5六⼩小時打通關 》
使⽤用 NodeJS + WebSocket
WebSocket是HTML5制定的標準,它是⼀一個基於HTTP的協定(Over
HTTP)
原則上,我們應該⾃自⾏行處理這⼀一系列的HTTP headers
⺫⽬目前有許多專⾨門WebSocket的NodeJS模組可使⽤用
⾮非NodeJS的官⽅方模組,要使⽤用npm⼯工具另外安裝
Copyright (C) 2013 Moko365 Inc. All Rights Reserved.
99
100. 《⼋八屏⼀一雲時代來臨 教你HTML5六⼩小時打通關 》
安裝 WebSocket-Node
https://github.com/Worlize/WebSocket-Node
利⽤用npm安裝WebSocket-Node:
➡ $ npm install websocket
Copyright (C) 2013 Moko365 Inc. All Rights Reserved.
100
101. 《⼋八屏⼀一雲時代來臨 教你HTML5六⼩小時打通關 》
引⼊入模組
需要,引⼊入不同的模組,總計4個:
➡ var WebSocketServer = require('websocket').server;
➡ var WebSocketClient = require('websocket').client;
➡ var WebSocketFrame = require('websocket').frame;
➡ var WebSocketRouter = require('websocket').router;
Copyright (C) 2013 Moko365 Inc. All Rights Reserved.
101
102. 《⼋八屏⼀一雲時代來臨 教你HTML5六⼩小時打通關 》
傳送 JSON Data
學會處理Query string與WebSocket後,下⼀一個⼯工作就是JSON
NodeJS服務器將資料打成為JSON格式後,再透過WebSocket回傳給
Client
Copyright (C) 2013 Moko365 Inc. All Rights Reserved.
102
103. 《⼋八屏⼀一雲時代來臨 教你HTML5六⼩小時打通關 》
File: server.js
第19~26⾏行:將原本的HTTP server封裝成WebSocket server,物件名為wsServer
第48⾏行:在wsServer裡註冊⼀一個Request handler,即onWsRequest()函數
第40⾏行:當WebSocket連線請求發⽣生時,回呼此函數
第41⾏行:接受此連線,第⼀一個參數是WebSocket protocol,這是⼀一個⾃自定的協定名
稱,⽤用途由開發者定義
第44~45⾏行:為此連線註冊Message handler與Close handler函數
第28⾏行:收到⽤用⼾戶端傳送過來的訊息時,回呼此函數,後續將繼續擴充此函數,將收到
的訊息儲存,並將訊息即時(Real-time)推送(Push)到所有的⽤用⼾戶端
第36⾏行:WebSocket連線關閉後,回呼此函數
Copyright (C) 2013 Moko365 Inc. All Rights Reserved.
103
104. 《⼋八屏⼀一雲時代來臨 教你HTML5六⼩小時打通關 》
File: server.js
1 var http = require("http");
2 var url = require("url");
3 var WebSocketServer = require('websocket').server;
4
5 function start(route, handlers) {
6 function onRequest(request, response) {
7 var pathname = url.parse(request.url).pathname;
8 var query = url.parse(request.url).query;
9
10 console.log("Request for " + pathname + " received.");
11
12 route(pathname, handlers, response, query);
13
14 response.writeHead(200, {"Content-Type": "text/plain"});
15 response.write("Hello World");
16 response.end();
17 }
18
19 var server = http.createServer(onRequest).listen(8888, function() {
20 console.log("Server has started and is listening on port 8888.");
21 });
22
23 wsServer = new WebSocketServer({
24 httpServer: server,
25 autoAcceptConnections: false
26 });
27
Copyright (C) 2013 Moko365 Inc. All Rights Reserved.
104
106. 《⼋八屏⼀一雲時代來臨 教你HTML5六⼩小時打通關 》
製作⽤用⼾戶端
1 <!DOCTYPE html>
2 <head>
3 </head>
4 <body>
5 <div id="header"></div>
6 <button onClick="WebSocketTest();">Get News</button>
7
8 <script type="text/javascript">
9 function WebSocketTest()
10 {
11 if ("WebSocket" in window)
12 {
13 // Let us open a web socket
14 var ws = new WebSocket("ws://svn.moko365.com:8888/", "echo-protocol");
15 ws.onopen = function(evt)
16 {
17 alert("open");
18 };
19 ws.onclose = function(evt)
20 {
21 alert("close");
22 };
23 }
24 else
25 {
26 // The browser doesn't support WebSocket
27 alert("WebSocket NOT supported by your Browser!");
28 }
29 }
30 </script>
31 </body>
32 </html>
Copyright (C) 2013 Moko365 Inc. All Rights Reserved.
106
107. 《⼋八屏⼀一雲時代來臨 教你HTML5六⼩小時打通關 》
重構為 jQuery 模式
8 <script type="text/javascript">
9 (function($) {
10 $.fn.createWebSocket = function () {
11
12 // This 'this' is '#message' object according to this sample
13 var div = this;
14
15 if ("WebSocket" in window)
16 {
17 alert("WebSocket is supported by your Browser!");
18 // Let us open a web socket
19 var ws = new WebSocket("ws://localhost:8888/start");
20 ws.onopen = function()
21 {
22 // Web Socket is connected, send data using send()
23 // eg, ws.send("Message to send");
24 };
25 ws.onmessage = function (evt)
26 {
27 var received_msg = evt.data;
28 div.html(received_msg);
29 };
Copyright (C) 2013 Moko365 Inc. All Rights Reserved.
107
108. 《⼋八屏⼀一雲時代來臨 教你HTML5六⼩小時打通關 》
cont...
30 ws.onclose = function()
31 {
32 // websocket is closed.
33
34 // 'this' here is [Object WebSocket]
35 div.html("<h1>onclose</h1>");
36 };
37 ws.onerror = function()
38 {
39 // 'this' here is [Object WebSocket]
40 div.html("<h1>onerror</h1>");
41 };
42 }
43 else
44 {
45 // The browser doesn't support WebSocket
46 alert("WebSocket NOT supported by your Browser!");
47 }
48 };
49
50 })($);
51
52 $("#message").createWebSocket();
53 </script>
Copyright (C) 2013 Moko365 Inc. All Rights Reserved.
108
109. 《⼋八屏⼀一雲時代來臨 教你HTML5六⼩小時打通關 》
How to Send Message
API: http://svn.moko365.com:8080/send?
u=<username>&m=<message>
➡ 1. HTML <form>
➡ 2. jQuery.ajax();
➡ 3. XmlHttpRequest
➡ 4. WebSocket.send();
Copyright (C) 2013 Moko365 Inc. All Rights Reserved.
109