一、基礎
1、HTTP協議是無狀態的,服務器只會響應來自客戶端的請求,但是它與客戶端之間不具備持續連接;且只能從客戶端主動請求服務端,服務端不能主動通知客戶端。
對於實時通信系統(聊天室或監控系統)這樣顯然是不合理的。傳統的方法有:長輪詢(客戶端每隔很短的時間,都對服務器發出請求,當時間足夠小就能實現實時的效果)、長連接(客戶端只請求一次,但是服務器會將連接保持,當有數據時就返回結果給客戶端)。這兩種方式,都對客戶端和服務器都造成了大量的性能浪費,於是WebSocket應運而生。WebSocket協議能夠讓瀏覽器和服務器全雙工實時通信,互相的,服務器也能主動通知客戶端。
2、 WebSocket的原理非常的簡單:利用HTTP請求產生握手,HTTP頭部中含有WebSocket協議的請求,所以握手之后,二者轉用TCP協議進行交流。
Socket.IO是業界良心,新手福音。它屏蔽了所有底層細節,讓頂層調用非常簡單。並且還為不支持WebSocket協議的瀏覽器,提供了長輪詢的透明模擬機制。
二、實現
1、socket.emit(action,arg1,arg2); 表示發送了一個action命令,還有兩個數據,在另一端接收時,可以這么寫: socket.on('action',function(arg1,arg2){...});
2、io.sockets.emit 信息傳輸對象為所有 client ; socket.emit 信息傳輸對象為當前 socket 對應的 client ,各個client socket 相互不影響;
socket.broadcast.emit 信息傳輸對象為所有 client ,排除當前socket 對應的 client
3、在使用Node的http模塊創建服務器同時還要Express應用,因為這個服務器對象需要同時充當Express服務和Socket.io服務。(如下)
var app = require('express')(); //Express服務 var server = require('http').Server(app); //原生Http服務 var io = require('socket.io')(server); //Socket.io服務 io.on('connection', function(socket){ /* 具體操作 */ }); server.listen(3000);
當客戶端需要連接服務器時,它需要先建立一個握手。io.處理連接事件,socket 處理斷開連接事件。在上面代碼里,這套握手機制是完全自動的,我們可以通過也可以io.use()方法來設置這一過程。
客戶端使用js調用socket.io的Client API即可。
<script src="/lib/socket.io/socket.io.js"></script> <script> var socket = io(); socket.on('connect', function() { /* 具體操作 */ }); </script>
4、同一個服務器可以使用namespaces創造不同的Socket連接。Socket.IO使用of()來指定不同的命名空間。
io.of('/someNamespace').on('connection', function(socket){
socket.on('customEvent', function(customEventData) {
/* 具體操作 */
});
});
io.of('/someOtherNamespace').on('connection', function(socket){
socket.on('customEvent', function(customEventData) {
/* 具體操作 */
});
});
服務器端則通過在定義Socket對象時傳遞namespace參數。
<script>
var someSocket = io('/someNamespace');
someSocket.on('customEvent', function(customEventData) {
/* 具體操作 */
});
var someOtherSocket = io('/someOtherNamespace');
someOtherSocket.on('customEvent', function(customEventData) {
/* 具體操作 */
});
</script>
在每一個namespace中又可以使用room來進一步划分,不過sockets是使用join()、leave()來調用。
//服務器端
io.on('event', function(eventData){
//監聽join事件
socket.on('join', function(roomData){
socket.join(roomData.roomName);
});
//監聽leave事件
socket.on('leave', function(roomData){
socket.leave(roomData.roomName);
});
});
//瀏覽器端
io.on('connection', function(socket){
//在此room下觸發事件
io. in('someRoom') .emit('customEvent', customEventData);
});
參考:http://www.cnblogs.com/edwardstudy/p/4358202.html
