LoginSignup
96
76

More than 5 years have passed since last update.

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

Last updated at Posted at 2019-03-03

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

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

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

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


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:

96
76
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
96
76