ぷるぷるの雑記

低レイヤーがんばるぞいなブログ. 記事のご利用は自己責任で.

Node.js & WebSocket の世界に入門した件

いままでApache + PHP しか使ったことがなかったので、思い切って入門してみた

実行環境

項目 バージョン
OS Windows11
Node.js 16.14.0 (LTS)
httpモジュール 0.0.1-security
wsモジュール 8.5.0

Node.jsのインストール

Windows版の場合ここから入手できる。安定をとってLTS版にしておいた。 インストーラーに言われるがまま次へを押していたらすぐに終わった。パスも自動的に追加されていたと思う。コマンドプロンプトでもCygwinターミナルでもよいのでnodeというコマンドを打ってみる。以下のように表示されていればインストール成功。

$ node
Welcom to Node.js v16.14.0
Type ".help" for more information.
>

npm init してみる

Node.js用のパッケージ管理ツールのうちの一つであるnpmを使ってみる。まずは通過儀礼としてnpmのバージョン確認をしてみる

$ npm -v
8.3.1

ずいぶんぶっきらぼうなんですね。npmはパッケージをインストールするだけではなくプロジェクトフォルダそのものを管理するツールみたい。ということで、テスト用のフォルダを作成し、その中でnpm initというコマンドを打ってみる。

$ mkdir test
$ cd test
$ npm init
This utility will walk you through creating a package.json file.
It only covers the most common items, and tries to guess sensible defaults.

See `npm help init` for definitive documentation on these fields
and exactly what they do.

Use `npm install <pkg>` afterwards to install a package and
save it as a dependency in the package.json file.

Press ^C at any time to quit.
package name: (test)
version: (1.0.0)
description:
entry point: (index.js)
test command:
git repository:
keywords:
author:
license: (ISC)
About to write to C:\cygwin64\home\tkhrk\test\package.json:

{
  "name": "test",
  "version": "1.0.0",
  "description": "",
  "main": "index.js",
  "scripts": {
    "test": "echo \"Error: no test specified\" && exit 1"
  },
  "author": "",
  "license": "ISC"
}


Is this OK? (yes)

途中プロジェクトに関する情報を求められるが、とりあえず空白のままEnterを押した。-yオプションをつけるとこの辺を自動でやってくれるらしい。npm init コマンドが完了すると、いつの間にやら設定ファイルが生成されている

$ ls
package.json

この中にはプロジェクト内で使用しているモジュールのバージョン情報や依存関係、ビルド用のスクリプトの設定が記されているみたい。npmを触る前はpipみたいなものかと思っていたが、Gradleに近い気もしてきた。

npmでパッケージをインストール

以下のコマンドで必要なモジュールをインストール

$ npm install http

added 1 package, and audited 2 packages in 2s

found 0 vulnerabilities

$ npm install ws

added 1 package, and audited 3 packages in 560ms

found 0 vulnerabilities

npm install したモジュールはプロジェクトフォルダ内に生成されるnode_modulesというフォルダに置かれている。また、同じく自動生成されるpackage-lock.jsonファイルにはインストールされたモジュールのバージョンや依存関係が記されている。おそらく、いじってはいけない項目だと思われる。

サーバー側のコードを書く

エントリポイントとなるindex.jsファイルを作成しサーバープログラムを書いていく。エントリポイントのファイルはpackage.jsonのmainで変更できそうだけど、現時点ではその必要もないでしょう。ネットでいろいろググり、しまいに次のようなコードを書いた。

const server = require('ws').Server;
const ws = new server({ port: 9000 });

ws.on('connection', (socket) =>{
    console.log('connected');

        // ブラウザから送られてきたメッセージをそのまま接続中のすべてのクライアントに返信する
    socket.on('message', (ms)=>{
        ws.clients.forEach( (client)=>{
            client.send(ms +':' + new Date());
        });
    });

        // コネクションが切断されたとき、サーバー側のコンソールにメッセージを表示する
    socket.on('close', ()=>{
        console.log('A client has left');
    });
});

Node.jsではサーバーの処理も書かなくてはいけないと聞いていたので大変そうだなーと思っていたが、モジュールを使えば何の苦労もなかった。

Chromeの開発者ツールからサーバーに接続する

残るはクライアント側のプログラムだが、わざわざhtmlにボタンを表示してクリックリスナーを登録して...とするのは面倒くさいのでChromeの開発者ツールのコンソールからサーバーに接続しよう。以下手順

1.Chromeを起動する

2.F12ボタンを押し開発者ツールを開く

3.Consoleタブを開きコマンドラインから以下のようにスクリプトを打つ

> const con = new WebSocket('ws://xxx.xxx.xxx.xxx:9000');
> con.send('hello');

4.Networkタブを開き、WSを選択するとNameという欄にサーバーのIPアドレスが表示されているのでクリックする。

f:id:prupru_prune:20220305213932p:plain
Chromeの開発者オプションのNetworkタブ

緑がサーバーに送信したメッセージで、赤がクライアントに送信されたメッセージの模様。複数のクライアントで同時に接続すると、確かにWebSocket通信になっていた。

まとめ

こんな簡単にWebSocket通信ができるとは思ってなかったので、感動した。

参考

qiita.com

qiita.com

qiita.com