Quantcast
Channel: Node.jsタグが付けられた新着記事 - Qiita
Viewing all articles
Browse latest Browse all 8936

npm ws のクライアントインスタンス生成,接続時イベントの登録,接続手続きの順番

$
0
0
node.jsで簡単にwebsocketの機能をつかえるようになるライブラリwsを つかっていて,サーバーの方はまあわかるとして,クライアントClass: Websocketの挙動がというか,設計がわかりにくかったので実験したらふぇぇって感じだった. (とはいえまあサーバーの方で大量に管理するクライアントの記述を思うとこれでちょうどいいのかもしれない.) 気になった点 クライアントクラスの実行例として以下のようなモノがGitにある client const WebSocket = require('ws'); const ws = new WebSocket('ws://www.host.com/path'); ws.on('open', function open() { const array = new Float32Array(5); for (var i = 0; i < array.length; ++i) { array[i] = i / 2; } ws.send(array); }); これだけである.簡単!と思えればいいのだけど, 素朴に考えると,接続完了時に発行される'open'に対するEventを登録(ws.on())してから接続を開始する気がする. しかしながらこの例には続きがなく,これで完結しており,実際別プロセスでws.Serverのサンプルプログラムを動かしてからこれを実行すると,ちゃんと動く. .on()は継承(?)しているEventなんとかクラスのものであって,Websocketクラス固有のものではない. したがって接続を開始するとしたらコンストラクタでしかありえない. 実際ソースを見てみると,そんな感じだった. 詳しくは見ておらず,間違っている可能性も大いにあるが,流れとしては クライアント: コンストラクタでいろいろ調整 クライアント: おそらくhttpでupgradeが承認されたとき用のイベントを登録 クライアント: httpでupgradeをhttpサーバーに要請 ここでコンストラクタの処理が終わる. そしてhttpサーバーがwssocketサーバーにアップグレードした旨が伝わり次第,クライアントにopenイベントが発行される. という感じであった. すなわち,ws.on()はコンストラクタの処理が終わって,サーバーからupgradeが通知されるまでの間に行われないと,'open'イベントをキャッチできない. 実験 実際以下のようなプログラムで比較するとわかる.ちなみにサーバー側ではsend(data)で送った内容(data)がそっくりそのまま返ってくる. const websocket = require("ws"); const sock = new websocket("ws://127.0.0.1:5001", { perMessageDeflate: false }); const openev = () => { sock.on("open", () => { console.log("event as connected "); }); } sock.on("message", data => { console.log("event as getting message from the server"); console.log("echo: " + data); }); sock.on("close", () => { console.log("event as closed"); }); ↑ここまで共有 Case 1: console.log("ws state:" + sock.readyState); openev(); //<-コンストラクタが終わってすぐくらいにopen event時のコールバック設定 //1s後にデータを送ってから接続を終える. setTimeout(() => { console.log("ws state:" + sock.readyState); sock.send('a'); sock.close(); }, 1000); 結果: ws state:0 event as connected ws state:1 event as getting message from the server echo: a event as closed case 2: console.log("ws state:" + sock.readyState); //openev(); //1s後にデータを送ってから接続を終える. setTimeout(() => { console.log("ws state:" + sock.readyState); openev(); //<-1s後にopen event時のコールバック設定 sock.send('a'); sock.close(); }, 1000); 結果: ws state:0 ws state:1 event as getting message from the server echo: echo back: a event as closed case 1とcase 2を比較するとws state:0とws state:1との間にあったevent as connectedが表示されなくなっている. といわけで,なんだか意図しないデータの取りこぼしとか起こりそうだなと思ってなんか気もち悪い気がしたというわけでした. ちなみに,コンストラクタで接続を開始せずに,あとから接続を開始できる関数がないか探しましたが見当たりませんでした.というか検索していると再接続もできないので,別のを作ったり使ってる人が見受けられました.もし接続用の関数があれば再接続もできるはずなので,やはりないのでしょう. ここまで書いて誰かすでにQiitaで記事書いてそう.だけどいい練習になったのでよし.

Viewing all articles
Browse latest Browse all 8936

Trending Articles