Help us understand the problem. What is going on with this article?

WebSocket(ブラウザAPI)とws(Node.js) の基本、自分用のまとめ

More than 1 year has passed since last update.

この投稿は、nodejsのwsとブラウザapiのWebSocketについて、自分の勉強のためにドキュメントを読みながら試しただけのものになります。

なのでWebSocketについての詳細な情報が欲しい方は、以下のリンクを見て、本記事は読まなくて良いです

wsのAPIドキュメントは↓のようです

間違っているなどあればご指摘お願いします :bow:


WebSocket仕様関連

ブラウザ対応状況

https://caniuse.com/#search=websocket

image.png

多くのブラウザでサポートされています

イベントリスナー

WebSocketapiは以下の4つのイベントを持っています

index.html
<!DOCTYPE html>
<html lang="ja">
<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <meta http-equiv="X-UA-Compatible" content="ie=edge">
    <title>Document</title>
</head>
<body>
    <button id="btn">Hello</button>

    <script>
        const sock = new WebSocket("ws://127.0.0.1:5001");

        sock.addEventListener("open", e => {
            console.log("接続が開かれたときに呼び出されるイベント");
        });

        sock.addEventListener("message", e => {
            console.log("サーバーからメッセージを受信したときに呼び出されるイベント");
        });

        sock.addEventListener("close", e => {
            console.log("接続が閉じられたときに呼び出されるイベント");
        });

        sock.addEventListener("error", e => {
            console.log("エラーが発生したときに呼び出されるイベント");
        });

        btn.addEventListener("click", e => {
            sock.send("hello");
        });
    </script>
</body>
</html>

WebSocketのサーバを動作させる

bash
npm init -y
npm i -D ws
package.json
{
  "name": "01_sample",
  "version": "1.0.0",
  "description": "",
  "main": "index.js",
  "scripts": {
    "test": "echo \"Error: no test specified\" && exit 1"
  },
  "keywords": [],
  "author": "",
  "license": "ISC",
  "devDependencies": {
    "ws": "^6.1.4"
  }
}
index.js
const server = require("ws").Server;
const s = new server({ port: 5001 });

s.on("connection", ws => {
    ws.on("message", message => {
        console.log("Received: " + message);

        if (message === "hello") {
            ws.send("hello from server");
        }
    });
});
bash
node index.js

open、messageイベントの確認

イベント起こしやすいようにボタンを追加しました

index.html
    <button id="btn">Hello</button>

    <script>
        const sock = new WebSocket("ws://127.0.0.1:5001");

        sock.addEventListener("open", e => {
            console.log("接続が開かれたときに呼び出されるイベント");
        });

        sock.addEventListener("message", e => {
            console.log("サーバーからメッセージを受信したときに呼び出されるイベント");
        });

        sock.addEventListener("close", e => {
            console.log("接続が閉じられたときに呼び出されるイベント");
        });

        sock.addEventListener("error", e => {
            console.log("エラーが発生したときに呼び出されるイベント");
        });

        btn.addEventListener("click", e => {
            sock.send("hello");
        });
    </script>

接続された時、サーバーからメッセージを受信した時にそれぞれイベントが実行されています

iJ3CrM4BgX.gif

messageイベントはe.dataからサーバーからの受信内容を受け取ることができます

javascript
        sock.addEventListener("message", e => {
            console.log(e.data);
        });

Screen Shot 2019-03-03 at 16.00.13.png


NetworkタブのWSからでもメッセージの内容を見ることができます。

  • 緑の矢印が送信したデータ
  • 赤の矢印がサーバーから受信したデータです

hX1Xp2HI75.gif

close、errorイベントの確認

ws.close()を実行すると、closeイベントが実行されるのが確認できました、

また、サーバーを停止した状態で接続しに行くと、エラーイベントが実行されるのも確認できました。

9TXHLR64Rq.gif

動作サンプル

サーバー側で接続が切れた場合の処理

index.js
const server = require("ws").Server;
const s = new server({ port: 5001 });

s.on("connection", ws => {
    ws.on("message", message => {
        ws.send("hello from server");
    });

    // 接続が切れた場合
    ws.on('close', () => {
        console.log('I lost a client');
    });
});

1P4bQhHCAy.gif

複数のクライアントにデータ送信する

index.js
const server = require("ws").Server;
const s = new server({ port: 5001 });

s.on("connection", ws => {
    ws.on('message', message => {

        ws.send("送信してきたクライアントのみに返す");

        s.clients.forEach(client => {
            client.send('接続しているクライアント全てに送信');
        });

        s.clients.forEach(client => {
            if (client !== ws)
                client.send('接続している自分以外のクライアント全てに送信');
        });
    });
});

bKQhunk5Uz.gif

動作サンプル

複数データの送受信

オブジェクトをJSON.stringify()とする

javascript
        const sock = new WebSocket("ws://127.0.0.1:5001");

        sock.addEventListener("message", e => {
            // サーバーから受信
            const { hoge, fuga, piyo } = JSON.parse(e.data);
            console.log(hoge, fuga, piyo);
        });

        btn.addEventListener("click", e => {
            // サーバーへ送信
            sock.send(JSON.stringify({
                name: 'alice',
                age: 25,
            }));
        });
index.js
const server = require("ws").Server;
const s = new server({ port: 5001 });

s.on("connection", ws => {
    ws.on('message', message => {
        // クライアントから受信
        const { name, age } = JSON.parse(message);
        console.log(name, age);

        // クライアントへ送信
        ws.send(JSON.stringify({
            hoge: true,
            fuga: [1, 3, 5],
            piyo: 0.5,
        }));
    });
});

UE7zT9jtvp.gif

動作サンプル

urlを確認する

WebSocket.urlで取得できる

image.png

接続状態を確認する

接続状態の定数が用意されています

参考:WebSocket - Web APIs | MDN

Constant Value
WebSocket.CONNECTING 0
WebSocket.OPEN 1
WebSocket.CLOSING 2
WebSocket.CLOSED 3

readyStateから現在の接続状態を取得できました

index.js
        const sock = new WebSocket("ws://127.0.0.1:5001");
        console.log(`readyState:${sock.readyState}`);

        sock.addEventListener("open", e => {
            console.log(`readyState:${sock.readyState}`);
        });

        sock.addEventListener("close", e => {
            console.log(`readyState:${sock.readyState}`);
        });

image.png


最後まで読んでいただいてありがとうございました :bow:

okumurakengo
人が作ってくれたご飯食べるときに何も言わずに食べるのは、ちょっとダメらしいという話を聞いたことがあるので、「あ、うめ、あ、うめ」って言いながら食ってたら、すごい変な人と思われてしまってしまった/初心者です、あまりわかっていません
https://bokete.jp/user/okumurakengo
qiitadon
Qiitadon(β)から生まれた Qiita ユーザー・コミュニティです。
https://qiitadon.com/
Why not register and get more from Qiita?
  1. We will deliver articles that match you
    By following users and tags, you can catch up information on technical fields that you are interested in as a whole
  2. you can read useful information later efficiently
    By "stocking" the articles you like, you can search right away