Node.js
簡易聊天室實作
今日範例
那我們會用到什麼
- Node.js(廢話
- npm
- socket.io
Nodejs是什麼
Node.js 是 Ryan Dahl 基於 Google 的 V8 引擎於 2009 年釋出的一個 JavaScript 開發平台,主要聚焦於 Web 程式的開發,通常用被來寫網站。
- 開源
- 跨平台
- 基於Javascript
- 非同步
Nodejs的特色
如何安裝
NPM
(Node Package Manager)
Javascript編寫的軟體套件管理系統,預設環境為Node.js
從 Node.js 0.6.3 版本開始,npm被自動附帶在安裝包中
# 安裝套件
$ npm install <moduleName>
# 安裝全域套件
$ npm install <moduleName> -g
# 移除套件
$ npm uninstall <moduleName>
# 移除全域套件
$ npm uninstall <moduleName> -g
npm 預設的模組可以從 http://npmjs.org 維護的public package registry 取得,模組可以使用 npm install 安裝:
npm 常用指令
# 檢查npm版本
$ npm --version
# 列出全域套件
$ npm ls -g
# 更新全域套件
$ npm update -g
# 更新專案套件
$ npm update
Socket.io
先別提socket你聽過websocket嗎
WebSocket 是 HTML5 開始提供的一種瀏覽器與伺服器之間,一個雙向通訊的網路技術
- client端(瀏覽器)發出HTTP訊息詢問server端能否使用websocket來溝通
- 若server端表示OK,則跳至Step 3
- client端使用websocket API中的onopen() 來建立websocket通道
- 建立通道後,server端則透過onmessage() 來傳遞訊息給client端
- client斷開連結後,送出onclose() 通知server端此次websocket的連線中斷
上面說了這麼多,說穿了其實就是瀏覽器在和伺服器互戳
那它的支援度如何呢?
貌似支援度挺高的呢(⁰▿⁰)
有什麼應用
安裝 Socket.IO
$ npm intall socket.io
建立基本 Server
var http = require('http');
var server = http.createServer();
server.listen(3000);
將這段程式碼儲存成 "server.js" 然後執行
node server.js
建立基本 Server
var http = require('http');
var server = http.createServer(function(req, res) {
res.writeHead(200, {'Content-Type': 'text/html'});
res.write('Hello, World!');
res.end();
});
console.log('3000');
server.listen(3000);
讓我們來看看剛剛那串咒文在做甚麼
// 載入http模組
var http = require('http');
// 利用內建的createServer架設一個基本的HTTP伺服器
// 用一個call back function接收HTTP伺服器的 request & response
// 最後HTTP伺服器需要設定listen的port,監聽所有HTTP伺服器行為
// 並同時將server收到的訊息顯示在終端上(console.log)
var server = http.createServer(function(req, res) {
// 接著使用 response.writeHead() 設定 HTTP 回應的標頭資訊
res.writeHead(200, {'Content-Type': 'text/html'});
// 接著設定網頁內容
res.write('Hello, World!');
// 最後結束整個定義過程
res.end();
});
console.log('3000');
server.listen(3000);
不過不可能都用
res.write
來寫網頁
var http = require("http");
var url = require('url');
var fs = require('fs');
var server = http.createServer(function(request, response) {
// 當伺服器接收到請求時,使用 url.parse() 函數解析出網址中所指定的路徑
// 可用 console.log(path) 來看看實際路徑解析的情形
var path = url.parse(request.url).pathname;
// 依照解析的路徑決定動作
switch (path) {
case '/':
response.writeHead(200, {'Content-Type': 'text/html'});
response.write('Hello, World.');
response.end();
break;
case '/socket.html':
// 若路徑為 /socket.html 則用fs 模組讀取socket.hthml檔案
fs.readFile(__dirname + path, function(err, data) {
// cheak讀取連結過程是否有誤
if (err){
//若連結過程有誤則回應404
response.writeHead(404);
response.write("opps this doesn't exist - 404");
} else {
//成功讀取則載入連結
response.writeHead(200, {"Content-Type": "text/html"});
response.write(data, "utf8");
}
// 最後一樣要記得加上 response.end() 結束整個處理流程的定義,讓它開始執行
response.end();
});
break;
default:
response.writeHead(404);
response.write("opps this doesn't exist - 404");
response.end();
break;
}
});
console.log('3000');
server.listen(3000);
那我們來對原本的程式修改"一點"
說好的一點哩Σ(;゚д゚)
莫驚慌聽我解釋
var url = require('url');
var fs = require('fs');
先來看看我們新引入的兩個小夥伴
url 是用來解析 URL 網址模組
fs 則是處理檔案模組
var path = url.parse(request.url).pathname;
當伺服器接收到請求時,使用 url.parse() 函數解析出網址中所指定的路徑
Input: 127.0.0.1:3000
Output: /
Input: 127.0.0.1:3000/socket.html
Output: /socket.html
可以加上
console.log(path)
試試看結果
定義檔案在讀取之後要進行什麼動作
fs.readFile(__dirname + path, function(error, data){...});
// error: 錯誤代碼,如果在讀取檔案出問題時(如檔案不存在),這個錯誤代碼就會被設定
// data: 檔案的內容
if (error){
response.writeHead(404);
response.write("opps this doesn't exist - 404");
}
else {
response.writeHead(200, {"Content-Type": "text/html"});
response.write(data, "utf8");
}
這裡我們先檢查讀取的過程是否有發生錯誤
如果檔案讀取成功的話,就輸出檔案的內容
<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8">
<title>SocketIO</title>
</head>
<body>This is our socket.html file</body>
</html>
建立一個
socket.html
檔案,內容如下
執行看看
server.js
,看看結果
var io = require('socket.io');
引入今天的主角 socket.io 模組
幫socket.html加入socket.io連線功能
<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8">
<title>SocketIO</title>
</head>
<body>
<div>This is our socket.html file</div>
<script src="/socket.io/socket.io.js"></script>
<script>
var socket = io.connect();
</script>
</body>
</html>
var serv_io = io.listen(server);
// on() 函數將特定的事件連接到指定的匿名函數
// 若websocket一建立連線,就會使用 emit() 函數來傳送資料
serv_io.sockets.on('connection', function(socket) {
console.log('hi~');
socket.emit('message', {'message': 'hello world'});
});
傳送資料至瀏覽器
這樣當瀏覽器呼叫
io.connection()
時就會呼叫這個匿名函數,重整網頁看看,terminal應該會跑出console.log的內容
並且使用
emit()
函數來傳送資料
socket.emit('message', {'message': 'hello world'});
emit()
會產生一個事件,格式如下:
socket.emit('事件名稱', '資料(Json)');
在伺服器建立連線後,瀏覽器也需要接收資料,所以需要在
socket.html
新增點東西
var socket = io.connect();
socket.on('message', function(data){
console.log(data.message);
});
到瀏覽器看看 console 內從server收到的東西
現在讓我們看看websocket厲害的地方
<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8">
<title>SocketIO</title>
</head>
<body>
<div id="date"></div>
<script src="/socket.io/socket.io.js"></script>
<script src="//ajax.googleapis.com/ajax/libs/jquery/1.11.0/jquery.min.js"></script>
<script>
var socket = io.connect();
socket.on('date', function(data) {
$('#date').text(data.date);
});
</script>
</body>
</html>
更改一下 socket.html
serv_io.sockets.on('connection', function(socket) {
// 傳送時間訊息給瀏覽器
setInterval(function() {
socket.emit('date', {'date': new Date()});
}, 1000);
});
修改一下
service.js
把
setInterval()
中時間的換成100(0.1sec)或是更短的時間,看看會發生甚麼事情
沒錯!它還是能運作ヽ(✿゚▽゚)ノ
Socket.IO 所擅長的其實是持續性的資料傳遞,是不是很棒棒
傳送資料至伺服器
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>socket.io</title>
</head>
<body>
<div id="date"></div>
<textarea id="text"></textarea>
<br>
<button id="btn">send</button>
<script src="//ajax.googleapis.com/ajax/libs/jquery/1.11.0/jquery.min.js"></script>
<script src="/socket.io/socket.io.js"></script>
<script>
var socket = io.connect();
socket.on('date', function(data) {
$('#date').text(data.date);
});
socket.on('message', function(data){
console.log(data.message);
})
$(document).ready(function(){
$('#btn').click(function() {
var msg_text = $('#text').val();
socket.emit('client_data', {
'letter': msg_text
});
$('#text').val('');
});
});
</script>
</body>
</html>
在網頁做點修改,增加textarea
傳送資料至伺服器
serv_io.sockets.on('connection', function(socket) {
setInterval(function() {
socket.emit('date', {'date': new Date()});
}, 1000);
socket.on('client_data', function(data) {
console.log(data.letter);
socket.emit('message', {'message': new Date() + " : " + data.letter})
})
});
在server.js做點修改讓伺服器能接收到來自瀏覽器的資料
現在你會聊天室應該要有的功能了
那一個聊天室應該會有什麼?
- 一個訊息輸入框
- 發送訊息按鈕
- 一個放大家留言的地方
- 暱稱欄位(?
- 一個訊息輸入框
- 發送訊息按鈕
- 一個放大家留言的地方
- 暱稱欄位(?
我在課程的github上有附了一個非常簡易的範例可以參考
投影片結束啦ヽ(✿゚▽゚)ノ
nodejs_socket
By jd615645
nodejs_socket
- 2,266