前面兩篇文章使用了Ajax long polling和WebSocket兩種經常使用的Web實時通訊方式構建了簡單的聊天程序。css
可是,因爲瀏覽器的兼容問題,不是全部的環境均可以使用WebSocket這種比較好的方式。也就是說,根據瀏覽器或者環境的不一樣,客戶端和服務端可能須要使用不一樣的通訊方式。html
爲了解決上面的問題,Socket.IO就出現了。jquery
Socket.IO是一個基於Nodejs的,用於實時通訊的一個軟件包(包括client端和server端),Socket.IO徹底由JavaScript實現。json
Socket.IO設計的目標是支持任何的瀏覽器,任何設備。在接口方面,Socket.IO統一了通訊的API,在內部實現上支持WebSocket,AJAX long-polling, AJAX multipart streaming, Forever Iframe等方式。也就是說,Socket.IO會根據環境來選擇適合的通訊方式。數組
在Socket.IO中,還有namespace和room的概念,能夠方便的對socket進行分組,方便的實現一些例如聊天室的應用。瀏覽器
關於更多Socket.IO相關的內容,請參考該連接。服務器
好吧,又是聊天程序,此次是Socket.IO版本。app
在實現方面,客戶端直接使用Socket.IO 的client,服務器端使用Nodejs。socket
客戶端首先建立一個socket對象,這個socket對象會監聽"new_message"和"user_status"事件。工具
var socket; function initSocket(){ socket = io("http://" + location.host); socket.emit("add_client", $("#clientNameSpan").text()); socket.on("new_message", function(data){ console.log(data); data = eval("(" + data + ")"); if (data.sender == $("#clientNameSpan").text()){ $("#inbox").append("<div class='chatItemS'><span class='msg mSend'><span class='sender'>"+data.sender+": </span>"+data.msg+"</span></div>"); } else { $("#inbox").append("<div class='chatItemR'><span class='msg mRecv'><span class='sender'>"+data.sender+": </span>"+data.msg+"</span></div>"); } $("#inbox").scrollTop($("#inbox")[0].scrollHeight); }); socket.on("user_status", function(data){ $("#clientCount").text("Online User: "+data.length); $("#clients").children().remove(); for(var i = 0; i<data.length; i++){ $("#clients").append("<span id='client'>"+data[i]["clientName"]+"</span>") } }) }
對於服務端,首先是一些靜態文件、頁面的處理。
// get the static files app.get("/", function(req, res){ res.sendFile(__dirname + "/index.html"); }); app.get("/static/jquery-1.11.3.js", function(req, res){ res.sendFile(__dirname + "/static/jquery-1.11.3.js"); }); app.get("/static/json2.js", function(req, res){ res.sendFile(__dirname + "/static/json2.js"); }); app.get("/static/style.css", function(req, res){ res.sendFile(__dirname + "/static/style.css"); });
另外,服務端主要的功能就是接收消息,而後廣播消息。
服務端會根據socket id和用戶名記錄全部的用戶,並存放在一個數組中。每當有用戶加入或者用戶退出,服務端就經過"user_status"事件將用戶數組發送給客戶端,這樣客戶端就能展現當前在先用戶數。
// save all the client {"sid": socket.id, "clientName": client} var clients = [] io.on("connection", function(socket){ socket.on("add_client", function(client){ console.log(client+" jion the chat"); var clientObj = {}; clientObj["sid"] = socket.id; clientObj["clientName"] = client; clients.push(clientObj); io.emit("user_status", clients) }); socket.on("new_message", function(msg){ console.log("Server got message: "+msg); console.log("Send message using: "+socket.conn.transport.name); io.emit("new_message", msg); }); socket.on("disconnect", function(){ for(var i = 0; i<clients.length; i++){ if(clients[i]["sid"] == socket.id){ console.log(clients[i]["clientName"]+" leave the chat"); clients.splice(i, 1); break; } } io.emit("user_status", clients); }); });
首先是一個login頁面,在服務端會將用戶名跟socket id綁定,用來進行簡單的用戶統計。
Console端打印了服務器收到的消息,以及用戶的join/leave狀況。
當用戶狀態改變後,頁面會收到"user_status"事件,而後更新用戶狀態欄。
前面提到了Socket.IO的優點就是統一了接口,對用戶屏蔽了底層,同時可以支持不一樣的設備,選擇最優的通訊方式。
下面就對Socket.IO的兼容性進行一些簡單的測試,主要看看IE7-10。
首先,注意服務端的下面一段代碼,用於顯示當前傳遞消息的通訊方式:
console.log("Send message using: "+socket.conn.transport.name);
我本機安裝的是IE10,經過服務端console能夠看到,在IE10中Socket.IO會選擇"WebSocket"爲最終通訊方式。
打開IE,經過F12進入下面頁面,而後設置爲IE9。
經過測試能夠看到,Socket.IO在IE9中能夠正常工做,因爲IE9不支持「WebSocket」,因此Socket.IO最終選擇了"Polling"爲最終通訊方式。
經過上面的設置切換到IE8模式,因爲IE8不支持「WebSocket」,因此Socket.IO就會將通訊方式切換到了「Polling」。
經過一樣的步驟測試,Socket.IO在IE7中使用polling方式正常工做。
IE7中惟一遇到的問題是「JSON.stringify」方法不支持,因此經過下面方式對IE7進行了hack:
<!--[if IE 7]> <script src="/static/json2.js"></script> <![endif]-->
從例子中能夠看到,使用了Socket.IO後,咱們只須要了解Socket.IO提供的API,而不須要關心使用哪一種通訊方式,使用起來簡單、方便。
文中對Socket.IO在IE上的兼容性作了一些簡單的測試,結果仍是很滿意的,對於不支持WebSocket的環境,Socket.IO自動切換到了polling方式,用戶不用去關心環境的差別了。
Socket.IO做爲一個跨環境,多種鏈接方式自動切換的工具,進一步簡化了Web實時通訊方面應用的開發。
Ps:經過此處能夠下載例子的源碼。