<html lang="en">
<head>
<meta charset="utf-8">
<title>Chat Room</title>
</head>
<body>
<div id="output">
</div>
<div id="send">
<input type="text" id="data" size="100" /><br />
<input type="button" id="sendtext" value="Send Text" />
</div>
</body>
</html>
這個 HTML 在 Browser 執行會是如下畫面有一個 Text Field 可以輸入文字然後有一個按鈕
接著加上一些 javascript,在 <head> </head> 中間。如下
<head>
<meta charset="utf-8">
<title>Chat Room</title>
<script src="http://localhost:8124/socket.io/socket.io.js"></script>
<script>
var socket = io.connect('http://localhost:8124');
socket.on('connect', function() {
socket.emit('addme', prompt('Who are you?'));
});
socket.on('chat',function(username, data) {
var p = document.createElement('p');
p.innerHTML = username + ': ' + data;
document.getElementById('output').appendChild(p);
});
window.addEventListener('load',function() {
document.getElementById('sendtext').addEventListener('click',function() {
var text = document.getElementById('data').value;
socket.emit('sendchat', text);
}, false);
}, false);
</script>
</head>
一開始這個文件用了 <script src="http://localhost:8124/socket.io/socket.io.js"> 因為要用到 socket.io 的功能,所以要指向 server 的 socket.io.js ,在 chat.html 使用 。我們一一來看一下。
var socket = io.connect('http://localhost:8124');
socket.on('connect', function() {
socket.emit('addme', prompt('Who are you?'));
});
這個是要用 io 去連結 server,然後就等待, connect 這個事件,也就是和 server 連上線後,就會觸發。觸發的動作就是發送一個訊息給 server 事件名為 addme,內容為 prompt('Who are you?')。prompt() 的用途是會跳出一個需要輸入的視窗,然後把使用者在這個視窗輸入的值,再經由 socket.emit 傳給 server。接著再來看一下,下一個 socket 事件socket.on('chat',function(username, data) {
var p = document.createElement('p');
p.innerHTML = username + ': ' + data;
document.getElementById('output').appendChild(p);
});
在 socket.on 等待 chat 事件,然後 server 會傳兩個值過來分別存在 username 和 data 這兩個變數中,接著更新網頁內容在 <output> 裡多加一個 <p> 內容就是某個 user 打了什麼字,這樣。在 Client 端最後,我們看到
window.addEventListener('load',function() {
document.getElementById('sendtext').addEventListener('click',function() {
var text = document.getElementById('data').value;
socket.emit('sendchat', text);
}, false);
}, false);
這個是新增按鈕按下去的觸發動作,主要就是把 TextField 中使用者輸入的文字,抓出來var text = document.getElementById('data').value;
然後再利用 socekt.emit 送給 server。這樣 Client 端就完成了。
Server 端也非常之簡單,如下就是全部了,存成 chatServer.js。
var app = require('http').createServer(handler)
, io = require('socket.io').listen(app)
, fs = require('fs');
app.listen(8124);
function handler (req, res) {
fs.readFile(__dirname + '/chat.html', function (err, data) {
if (err) {
res.writeHead(500);
return res.end('Error loading chat.html');
}
res.writeHead(200);
res.end(data);
});
}
io.sockets.on('connection', function (socket) {
socket.on('addme',function(username) {
socket.username = username;
socket.emit('chat', 'SERVER', 'You have connected');
socket.broadcast.emit('chat', 'SERVER', username + ' is on deck');
});
socket.on('sendchat', function(data) {
io.sockets.emit('chat', socket.username, data);
});
socket.on('disconnect', function() {
io.sockets.emit('chat', 'SERVER', socket.username + ' has left the building');
});
});
一開始需要用到 http,socket.io,fs 等 module 就引用就好了。然後來看一下 handler 這個 function 被用在一開始的 require('http').createServer(handler) 。function handler (req, res) {
fs.readFile(__dirname + '/chat.html', function (err, data) {
if (err) {
res.writeHead(500);
return res.end('Error loading chat.html');
}
res.writeHead(200);
res.end(data);
});
}
這個 funciton 主要是說不管 client 端在 Browser 輸入什麼路徑,都是執行這個 function ,無論是輸入http://127.0.0.1:8124/ashdf;asdlf/has;dfasdf
或是
http://127.0.0.1:8124/
結果都是一樣的,就是把同一個目錄下的 chat.html 讀出來然後送給 Browser, 也就是說,現在 Browser 看到的就是一開始我們寫的 chat.html ,一個 Text Field 和一個按鈕的樣式。
io.sockets.on('connection', function (socket) {
socket.on('addme',function(username) {
socket.username = username;
socket.emit('chat', 'SERVER', 'You have connected');
socket.broadcast.emit('chat', 'SERVER', username + ' is on deck');
});
socket.on('sendchat', function(data) {
io.sockets.emit('chat', socket.username, data);
});
socket.on('disconnect', function() {
io.sockets.emit('chat', 'SERVER', socket.username + ' has left the building');
});
});
接著看到一滿大的 function,就是 io.socket.on 等待 connection 事件,
然後會得到一個 socket 也就是和一個 client 連上線。要注意的是這個 socket 會因為不同的 client 而有不同的記憶體
接著看裡面一點
socket.on('addme',function(username) {
socket.username = username;
socket.emit('chat', 'SERVER', 'You have connected');
socket.broadcast.emit('chat', 'SERVER', username + ' is on deck');
});
然後這個 socket 會等待 addme 這個事件,會得到一個 username 再存到 socket.name 保存下來。
然後用 socket.emit 回給連上來的 client,再用 socket.broadcast.emit 廣播給所有在線上其他的client。接著再往下看。socket.on('sendchat', function(data) {
io.sockets.emit('chat', socket.username, data);
});
這個 socket 等待 sendchat 的事件,然後收到資料後用 io.sockets.emit 廣播給所有線上的 client。說到這裡,我們來看這三個相似的 function- socket.emit - 對於一個特定的 socket 傳訊息
- socket.broadcast.emit - 對於除了目前這個 socket 之外所有線上的 socket 傳訊息
- io.sockets.emit - 對於所有線上 socket 傳訊息
socket.on('disconnect', function() {
io.sockets.emit('chat', 'SERVER', socket.username + ' has left the building');
});
也就是 socket 等待 disconnect 之後,就廣播給其他 client 說某 socket 離線了。 先執行 node chatServer.js測試的方法就是用兩個不同的 Browser 試試連看看,這樣就可以互相聊天了。
原始碼都放在 GitHub。
補充說明一下,在這個例子我們都使用 socket.emit() 來傳送訊息,也許讀者有參考到其他教學有用到 socket.send() 這個 function,我們用一個例子來解釋
socket.send("Hi") - 相當於 socket.emit("message", "Hi");也就是說,socket.send("Hi") 省略了 socket.emit("message", "Hi"); 前面的第一個 "message",而接受的一端就是用
socket.on('message', function (message) {
console.log(message);
});
來接收 socket.send("Hi") 的訊息。
你好,謝謝你的分享,但我有個問題想問,
回覆刪除我用node.js架起server後,
在本機可以執行,但將自己的電腦當作server別人卻連不進來,
不知道要用本機架設server還需要其他步驟嗎?謝謝!
這個是Public IP 的問題,如果您不懂的話,需要請教有架過站的朋友哦。用說的說半天也會搞的很不清楚。
回覆刪除您好,感謝您的分享,有一些問題想請教您
回覆刪除如果要把聊天的內容記錄下來,例如記錄在一個檔案裡,請問要怎麼做呢?
謝謝!
還請參考這幾篇文章。http://blog.allenchou.cc/nodejs-tuts-3-use-filesystem/ 和 http://ccckmit.wikidot.com/js:nodefile
回覆刪除請問用 android 當作client的話 server 仍是node.js
回覆刪除有範例可以介紹嗎
或者用 android 的 webview 載入 網頁IP
回覆刪除不過該如何修改?
謝謝清楚的講解
回覆刪除