web-dev-qa-db-ja.com

Node.js Socket.ioページが複数の接続を更新する

私はsocket.io(1.5)を使用してこの単純なnode.jsサーバーコードを持っています:

var io = require('socket.io').listen(8080);

io.on('connection', function(socket) {

    console.log(' %s sockets connected', io.engine.clientsCount);

    socket.on('disconnect', function() {
        console.log("disconnect: ", socket.id);
    });
});

このコードを実行してF5キーを数回押すと、古い接続が切断される前に、新しい接続が作成される場合があります。しばらくすると、ハートビートティムアウトだと思います。すべての接続が閉じられます。結果を見る:

 2 sockets connected
 3 sockets connected
 4 sockets connected
 5 sockets connected
 6 sockets connected
 7 sockets connected
 8 sockets connected
 9 sockets connected
 10 sockets connected
 11 sockets connected
disconnect:  0h_9pkbAaE3ftKT9AAAL
 11 sockets connected
 12 sockets connected
 13 sockets connected
 14 sockets connected
disconnect:  oB4HQRCOY1UIvvZkAAAP
 14 sockets connected
 15 sockets connected
disconnect:  LiIN0oDVoqbePgxFAAAR
 15 sockets connected
 16 sockets connected
 17 sockets connected
 18 sockets connected
disconnect:  zxvk-uhWABHzmu1uAAAV
 18 sockets connected
 19 sockets connected
 20 sockets connected
disconnect:  FlboxgTzcjf6ScffAAAY
 20 sockets connected
 21 sockets connected
disconnect:  9UGXbnzukfGX_UtWAAAa
 21 sockets connected
disconnect:  pAfXOEz6RocKZdoZAAAb
 21 sockets connected
disconnect:  DIhTyVgG2LYBawaiAAAc
 21 sockets connected
disconnect:  W4XOc1iRymfTE2U0AAAd
 21 sockets connected
disconnect:  WZzegGPcoGDNLRTGAAAe
 21 sockets connected
 22 sockets connected
disconnect:  KVR3-fYH0cz77BmgAAAC
disconnect:  ANQknhnxr4l-OAuIAAAD
disconnect:  KZE5orNx6u9MbOArAAAE
disconnect:  TS6LL3asXrcznfcPAAAF
disconnect:  SVNxS3I7KqecdqKhAAAG
disconnect:  IE2WE5Y0PJzvxgBfAAAH
disconnect:  v69bdJav9PjpThBGAAAI
disconnect:  mJKT1ggfOOTshZKgAAAJ
disconnect:  YlycVjdcWe0emCAcAAAK
disconnect:  MoIDJSzP_L-1RUwuAAAM
disconnect:  wAl0x5qwCkrnDDYQAAAN
disconnect:  eiTlPEk2Hx_X-L-fAAAO
disconnect:  KgkrXxzG_EpXOsPTAAAQ
disconnect:  Lvf3kK-6XXEbu3NWAAAS
disconnect:  -hOoGdYOIvVK04K_AAAT
disconnect:  3EUmaAYpK-U3Ss9tAAAU
disconnect:  HQ6M98FebtKlU3OfAAAW
disconnect:  OwgrbRBYbS4j84nmAAAX
disconnect:  yN8FZAP4RjUNl2MeAAAZ
disconnect:  K9IFTjlgAWzdNfpUAAAf

私の質問は、これはバグですか、それともsocket.ioの通常の動作ですか? F5キーを押すだけで、接続のフラッディングを防ぐにはどうすればよいですか?

よろしくマルク

14
mcbookwood

私は自分のテストアプリを作成し、何が起こっているのかを理解することができました。

F5を非常に高速で複数回押すと、一時的に余分なsocket.io接続がChromeに蓄積されますが、比較的短時間(おそらく数分)で回復し、接続されたソケットの総数が1に戻ります。

さらにテストしたところ、これはブラウザの問題ではないことがわかりました。これは、socket.ioがsocket.io接続を開始する方法に関する問題です。これをクライアントで置き換える場合:

var socket = io();

これとともに:

var socket = io({transports: ['websocket'], upgrade: false});

これにより、socket.ioがwebSocketのみを使用し、HTTPポーリングを使用しないように強制されるため、問題は解消します。

つまり、socket.ioのデフォルトの動作は、socket.io接続のhttpポーリングバージョンで開始することです。少量のデータが交換された後、socket.ioは実際のwebSocketへの切り替えを試みます。その実際のwebSocketが機能する場合、httpポーリング接続の使用を停止します。

ただし、ポーリングと実際のwebSocketとの間のこの移行の途中でF5を押すと、socket.ioがまだ通信しているWebページがなくなったことを知るための永続的な接続はまだありません。したがって、それができることは、しばらくしてそのWebページからの着信通信がなくなったことを理解することです。したがって、それはsocket.io接続をクリアする必要があります(F5を押したときにポーリングモードでした)。

ただし、上記のクライアントコードで初期ポーリングモードをオフにすると、実際のWebSocketのみが使用され(シミュレートされたポーリングモードは使用されません)、F5を押したときにブラウザーがWebSocketをクリーンアップするのが非常に優れているため、サーバーはsocket.io接続の確立が完了していない(この場合、一時的に孤立する接続はまだありません)か、すでにwebSocketに変換されています(ブラウザはF5でそれを完全に閉じます)。

したがって、これは、socket.ioが開始するhttpポーリングモードの設計上の制限です。そのモードでは継続的な接続がないため、そのページがF5に置き換えられたときにブラウザーからすぐに通知されず、サーバーはクライアントがちょうど消えたことを知る方法はありません。ただし、httpポーリングモードをスキップして実際のwebSocketで開始する場合、socket.io接続があるような時間帯はありませんが、実際のwebSocketはないため、サーバーは常にwebSocketを閉じるブラウザーによって即座に通知されますページが消えたときの接続。

25
jfriend00