Web實時通信之Socket.IO


前面兩篇文章使用了Ajax long polling和WebSocket兩種常用的Web實時通信方式構建了簡單的聊天程序。

但是,由於瀏覽器的兼容問題,不是所有的環境都可以使用WebSocket這種比較好的方式。也就是說,根據瀏覽器或者環境的不同,客戶端和服務端可能需要使用不同的通信方式。

Socket.IO簡介

為了解決上面的問題,Socket.IO就出現了。

Socket.IO是一個基於Nodejs的,用於實時通信的一個軟件包(包括client端和server端),Socket.IO完全由JavaScript實現。

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版本。

實現

在實現方面,客戶端直接使用Socket.IO 的client,服務器端使用Nodejs。

客戶端

客戶端首先創建一個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的優勢就是統一了接口,對用戶屏蔽了底層,同時能夠支持不同的設備,選擇最優的通信方式。

下面就對Socket.IO的兼容性進行一些簡單的測試,主要看看IE7-10。

首先,注意服務端的下面一段代碼,用於顯示當前傳遞消息的通信方式:

console.log("Send message using: "+socket.conn.transport.name);

IE10

我本機安裝的是IE10,通過服務端console可以看到,在IE10中Socket.IO會選擇"WebSocket"為最終通信方式。

IE9/IE8

打開IE,通過F12進入下面頁面,然后設置為IE9。

通過測試可以看到,Socket.IO在IE9中可以正常工作,由於IE9不支持“WebSocket”,所以Socket.IO最終選擇了"Polling"為最終通信方式。

通過上面的設置切換到IE8模式,由於IE8不支持“WebSocket”,所以Socket.IO就會將通信方式切換到了“Polling”。

IE7

通過同樣的步驟測試,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:通過此處可以下載例子的源碼。

 


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM