2013-10-18 41 views
2

我面臨着一個奇怪的問題,我自己無法解決。我建立了一個安裝程序,通過Django/Celery定期任務發送JSON序列化消息。此任務通過Redis與node.js服務器進行通信。 Node.js通過使用webbrowser的socket.io來處理通信。Redis + Node.js + Socket.io + Django/Celery設置中的奇怪行爲。斷開連接的插座仍然收到消息

的Django /芹菜任務

@periodic_task(run_every=crontab()) # every minute 
def process_channels(): 
    r = redis.StrictRedis(host='localhost', port=6379, db=0) 

    for i in xrange(1,21): # 1..20 
     data_dict = {} 
     data_dict['time'] = time.ctime(time.time()) 
     data_dict['message'] = os.urandom(10).encode('hex') 
     r.publish('channel', json.dumps(data_dict)) 
     time.sleep(2) 

的node.js服務器

var http = require('http'); 
var server = http.createServer().listen(4000); 
var io = require('socket.io').listen(server); 
var querystring = require('querystring') 
var redis = require('socket.io/node_modules/redis'); 
var sub = redis.createClient(); 

sub.subscribe('channel'); 

io.sockets.on('connection', function (socket) { 
    // grab message from Redis and send to client 
    sub.on('message', function(channel, message) { 
     console.log(message + ' ' + channel + ' ' + socket.id); 
     socket.send(message); 
    }); 

    socket.on('disconnect', function() { 
     console.log('disconnected') 
    }); 
}); 

的index.html

$(document).ready(
    function() { 
     var socket = io.connect('localhost', { 
       port: 4000 
     }); 

     socket.on('connect', function() { 
       console.log("connecting"); 
     }); 

     socket.on('message', function(message) { 
      // deserialize message from DJANGO 
      var data = JSON.parse(message); 

      //Append message to the bottom of the list 
      $('#comments').append('Time: ' + data.time + '<br />'); 
      $('#comments').append('Message: ' + data.message + '<br /><br />'); 
      } }); 
    }); 

漂亮簡單。該任務通過Redis將隨機生成的消息發送到將其發送到瀏覽器的節點服務器。正如你所看到的,我在節點服務器中記錄了消息和socket.id。

一切正常,直到我做一個頁面重新加載。當網頁加載完畢後,第一次在服務器控制檯打印類似的東西:

{"message": "85105676e21512a33e72", "time": "Fri Oct 18 22:33:10 2013"} channel 94k39P2j9dMv1JEZRW6Q 

當我做一個頁面刷新顯示:

disconnected 
{"message": "c3e93646d60a5a6727f6", "time": "Fri Oct 18 22:33:18 2013"} channel 94k39P2j9dMv1JEZRW6Q 
{"message": "c3e93646d60a5a6727f6", "time": "Fri Oct 18 22:33:18 2013"} channel wJwsRvpgEks7g1AURW6R 

同樣的消息已發送兩次。每次我重新加載頁面時,都會再次發送消息。查看socket.ids(第3個字段),它似乎是在重新加載之前套接字沒有正確斷開,並且服務器仍然通過該套接字發送消息。我不明白這種行爲。 'disconnect'方法被調用,所以應該以任何方式處理。有人可以幫我嗎?

非常感謝提前。

+0

在黑暗中拍攝,但也許考慮在客戶端設置'強制新連接'爲真? –

回答

0

在客戶端嘗試使用socket.once()而不是socket.on()。

socket.once('message', function() { 
    ... 
} 

問題可能是,每次重新加載頁面時,都會附加多個偵聽器。我面臨類似的問題,'.once()'是我能找到的唯一解決方案。

如果這沒有幫助,你可以嘗試探索在這裏發佈的類似問題。希望它有幫助:) https://github.com/LearnBoost/socket.io/issues/997