私は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キーを押すだけで、接続のフラッディングを防ぐにはどうすればよいですか?
よろしくマルク
私は自分のテストアプリを作成し、何が起こっているのかを理解することができました。
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を閉じるブラウザーによって即座に通知されますページが消えたときの接続。