1024_(即時通訊)使用node.js和socket.io實現多人聊天室
使用node.js和socket.io實現多人聊天室
2015年01月24日 03:24:54 遠古大猛獁 閱讀數:2775
轉自:
http://www.cnblogs.com/flyoung2008/archive/2012/07/19/2600132.html
http://blog.fens.me/nodejs-socketio-chat/
一、基本功能
1、使用者隨意輸入一個暱稱即可登入
2、登入成功後
1) 對正在登入使用者來說,羅列所有線上使用者列表,羅列最近的歷史聊天記錄
2) 對已登入的使用者來說,通知有新使用者進入房間,更新線上使用者列表
3、退出登入
1)支援直接退出
2) 當有使用者退出,其他所有線上使用者會收到資訊,通知又使用者退出房間,同時更新線上使用者列表
4、聊天
1) 聊天就是廣播,把資訊廣播給所有連線線上的使用者
5、一些出錯處理
1) 暫時簡單處理了系統邏輯錯誤、網路出錯等特殊情況的出錯提示
問題:功能不完善,有bug(退出後,新使用者重新登入,還是原來的使用者) 。抽空完善吧
二、技術介紹
socket.io(官網:http://socket.io/)是一個跨平臺,多種連線方式自動切換,做即時通訊方面的開發很方便,而且能和expressjs提供的傳統請求方式很好的結合,即可以在同一個域名,同一個埠提供兩種連線方式:request/response, websocket(flashsocket,ajax…)。
這篇文章對socket.io的使用做了詳細介紹:http://www.cnblogs.com/dxy1982/archive/2012/01/30/2328020.html
《用node.js和Websocket做個多人聊天室吧》
三、注意事項
(1)客戶端這樣引用socket.io.js:
<script src="/socket.io/socket.io.js"></script>
可能會載入失敗(我在這裡耗了不少時間)
可以改為:
<script src="http://ip:port/socket.io/socket.io.js"></script>
(對應伺服器的ip地址和埠號,比如說localhost和80埠)
(2)實現廣播的時候,參考官網的寫法,竟然不起作用,如:
var io = require('socket.io').listen(80); io.sockets.on('connection', function (socket) { socket.broadcast.emit('user connected'); socket.broadcast.json.send({ a: 'message' }); });
後來看了這個:http://stackoverflow.com/questions/7352164/update-all-clients-using-socket-io
改為以下才起作用:
io.sockets.emit('users_count', clients);
四、效果圖
五、原始碼下載
ps:
1、在命令列執行
node main.js
然後在瀏覽器中開啟index.html,如果瀏覽器(ff、Chrome)不支援,請升級到支援WebSocket的版本.
2、推薦node.js的IDE WebStorm
=============================================================================================================================
前言
網路聊天室在web1.0的時代就出現了,但當時技術支援比較有限,大都是通過瀏覽器外掛BHO,JavaApplet,Flash實現的。如今HTML5技術風起雲湧,通過websocket實現的網路聊天室,被定義為websocket的第一個實驗,就像Hello World一樣的簡單。
今天我也動手完成了這個實驗,感覺真的很爽!
目錄
- socket.io介紹
- 伺服器端和客戶端通訊設計
- 伺服器端實現
- 客戶端實現
- 完整案例程式碼
1. socket.io介紹
socket.io一個是基於Nodejs架構體系的,支援websocket的協議用於時時通訊的一個軟體包。socket.io 給跨瀏覽器構建實時應用提供了完整的封裝,socket.io完全由javascript實現。
基於Nodejs實現webscoket其他的框架,請參考文章:Nodejs實現websocket的4種方式
2. 伺服器端和客戶端通訊設計
上圖中client1 和 server 描述通訊過程,client2描述對其他的客戶端,通過廣播進行訊息通訊。
- client1向server發起連線請求
- server接受client的連線
- client1輸入登陸使用者名稱
- server返回歡迎語
- server通過廣播告訴其他線上的使用者,client1已登陸
- client1傳送聊天資訊
- server返回聊天資訊(可省略)
- server通過廣播告訴其他線上的使用者,client1的聊天訊息
- client1關閉連線,退出登陸
- server通過廣播告訴其他線上的使用者,client1已退出
- 左邊: aaa 登陸
- 右邊: bbb 登陸
- 左邊: aaa 收到 bbb登陸歡迎訊息
- aaa 和 bbb 實現對話
- 右邊: bbb 重新整理瀏覽自動退出
- 左邊: aaa 收到 bbb的退出訊息
- 右邊: CCC 登陸
- 左邊: aaa 收到 CCC 登陸歡迎訊息
- aaa 和 CCC 實現對話
3. 伺服器端實現
我們這裡使用socket.io和express3的混合模式,讓HTTP請求和WebSocket請求都使用3000埠。
伺服器端實現,只有一個核心檔案app.js。
-
//引入程式包
-
var express = require('express')
-
, path = require('path')
-
, app = express()
-
, server = require('http').createServer(app)
-
, io = require('socket.io').listen(server);
-
//設定日誌級別
-
io.set('log level', 1);
-
//WebSocket連線監聽
-
io.on('connection', function (socket) {
-
socket.emit('open');//通知客戶端已連線
-
// 列印握手資訊
-
// console.log(socket.handshake);
-
// 構造客戶端物件
-
var client = {
-
socket:socket,
-
name:false,
-
color:getColor()
-
}
-
// 對message事件的監聽
-
socket.on('message', function(msg){
-
var obj = {time:getTime(),color:client.color};
-
// 判斷是不是第一次連線,以第一條訊息作為使用者名稱
-
if(!client.name){
-
client.name = msg;
-
obj['text']=client.name;
-
obj['author']='System';
-
obj['type']='welcome';
-
console.log(client.name + ' login');
-
//返回歡迎語
-
socket.emit('system',obj);
-
//廣播新使用者已登陸
-
socket.broadcast.emit('system',obj);
-
}else{
-
//如果不是第一次的連線,正常的聊天訊息
-
obj['text']=msg;
-
obj['author']=client.name;
-
obj['type']='message';
-
console.log(client.name + ' say: ' + msg);
-
// 返回訊息(可以省略)
-
socket.emit('message',obj);
-
// 廣播向其他使用者發訊息
-
socket.broadcast.emit('message',obj);
-
}
-
});
-
//監聽出退事件
-
socket.on('disconnect', function () {
-
var obj = {
-
time:getTime(),
-
color:client.color,
-
author:'System',
-
text:client.name,
-
type:'disconnect'
-
};
-
// 廣播使用者已退出
-
socket.broadcast.emit('system',obj);
-
console.log(client.name + 'Disconnect');
-
});
-
});
-
//express基本配置
-
app.configure(function(){
-
app.set('port', process.env.PORT || 3000);
-
app.set('views', __dirname + '/views');
-
app.use(express.favicon());
-
app.use(express.logger('dev'));
-
app.use(express.bodyParser());
-
app.use(express.methodOverride());
-
app.use(app.router);
-
app.use(express.static(path.join(__dirname, 'public')));
-
});
-
app.configure('development', function(){
-
app.use(express.errorHandler());
-
});
-
// 指定webscoket的客戶端的html檔案
-
app.get('/', function(req, res){
-
res.sendfile('views/chat.html');
-
});
-
server.listen(app.get('port'), function(){
-
console.log("Express server listening on port " + app.get('port'));
-
});
-
var getTime=function(){
-
var date = new Date();
-
return date.getHours()+":"+date.getMinutes()+":"+date.getSeconds();
-
}
-
var getColor=function(){
-
var colors = ['aliceblue','antiquewhite','aqua','aquamarine','pink','red','green',
-
'orange','blue','blueviolet','brown','burlywood','cadetblue'];
-
return colors[Math.round(Math.random() * 10000 % colors.length)];
-
}
4. 客戶端實現
這裡我們需要定義幾個檔案:chat.html, chat.js, jquery.min.js, main.css
1). views/chat.html
-
<!DOCTYPE html>
-
<html>
-
<head>
-
<meta charset="utf-8">
-
<title>Socket.io - Simple chat</title>
-
<link rel="stylesheet" type="text/css" href="css/main.css">
-
<script src="javascripts/jquery.min.js"></script>
-
<script src="/socket.io/socket.io.js"></script>
-
<script src="javascripts/chat.js"></script>
-
</head>
-
<body>
-
<h1>Socket.io - Simple chat room</h1>
-
<div>
-
<span id="status">Connecting...</span>
-
<input type="text" id="input"/>
-
</div>
-
<div id="content"></div>
-
</body>
-
</html>
2). public/javascript/chat.js
-
$(function () {
-
var content = $('#content');
-
var status = $('#status');
-
var input = $('#input');
-
var myName = false;
-
//建立websocket連線
-
socket = io.connect('http://localhost:3000');
-
//收到server的連線確認
-
socket.on('open',function(){
-
status.text('Choose a name:');
-
});
-
//監聽system事件,判斷welcome或者disconnect,列印系統訊息資訊
-
socket.on('system',function(json){
-
var p = '';
-
if (json.type === 'welcome'){
-
if(myName==json.text) status.text(myName + ': ').css('color', json.color);
-
p = '<p style="background:'+json.color+'">system @ '+ json.time+ ' : Welcome ' + json.text +'</p>';
-
}else if(json.type == 'disconnect'){
-
p = '<p style="background:'+json.color+'">system @ '+ json.time+ ' : Bye ' + json.text +'</p>';
-
}
-
content.prepend(p);
-
});
-
//監聽message事件,列印訊息資訊
-
socket.on('message',function(json){
-
var p = '<p><span style="color:'+json.color+';">' + json.author+'</span> @ '+ json.time+ ' : '+json.text+'</p>';
-
content.prepend(p);
-
});
-
//通過“回車”提交聊天資訊
-
input.keydown(function(e) {
-
if (e.keyCode === 13) {
-
var msg = $(this).val();
-
if (!msg) return;
-
socket.send(msg);
-
$(this).val('');
-
if (myName === false) {
-
myName = msg;
-
}
-
}
-
});
-
});
3). public/javascript/jquery.min.js
從jquery官方下載: http://jquery.com/
4). public/css/main.css
-
* {padding:0px; margin:0px;}
-
body{font-family:tahoma; font-size:12px;margin:10px;}
-
p {line-height:18px;padding:2px;}
-
div {width:500px;}
-
#content {
-
padding:5px;
-
background:#ddd;
-
border-radius:5px;
-
border:1px solid #CCC;
-
margin-top:10px;
-
}
-
#input {
-
border-radius:2px;
-
border:1px solid #ccc;
-
margin-top:10px;
-
padding:5px;
-
width:380px;
-
}
-
#status {
-
width:100px;
-
display:block;
-
float:left;
-
margin-top:15px;
-
}
5. 完整案例程式碼
專案已經上傳到github: https://github.com/bsspirit/chat-websocket
下載,安裝,啟動伺服器
-
git clone https://github.com/bsspirit/chat-websocket.git
-
npm install
-
node app.js
開啟瀏覽器
可以多開啟幾個視窗,模擬不同使用者有的對話。
http://localhost:3000
做完實驗,感覺棒極了。技術創新的革命!!