1. ホーム
  2. Web制作
  3. html5

5分でわかるHTML5 WebSocketプロトコル

2022-02-06 21:21:46

1. 背景

プッシュ技術を実装するために多くのウェブサイトで使われている技術にAjaxポーリングがあります。ポーリングとは、一定時間ごとにブラウザからサーバにHTTPリクエストを行い、サーバからクライアントブラウザに最新データを返すというものです。この従来のモデルは、ブラウザがサーバーにリクエストを送り続ける必要があるという明らかな欠点があるが、HTTPリクエストには長いヘッダーが含まれることがあり、そのうち実際に有効なデータはごく一部なので、明らかに多くの帯域やその他のリソースを浪費している。そのため、サーバーのリソースや帯域を節約し、リアルタイムな通信を可能にします。

2. WebSocketの紹介

従来のhttpもプロトコルであるが、WebSocketはhttpサーバーでは実装できないプロトコルである。

2.1. ブラウザ対応

主要なブラウザでサポートされています

2.2. メリット

httpでは、以下のようなメリットがあります。

1. クライアントはサーバーとの間に1つのTCP接続を確立するだけなので、使用する接続数を少なくすることができます。

2. WebSocket サーバー側が能動的にデータをクライアントにプッシュできるため、より柔軟で効率的な運用が可能です。

3. プロトコルヘッダを軽量化し、転送データ量を削減。

ロータルトレーニング機構との対比

3. WebSocketの使用方法

WebSocketが何であり、何を提供するかを理解した上で、どのように使用するか?

3.1. WebSocketの作成

WebSocket は、http とは少し異なる url パターンのカスタム プロトコルを使用します。暗号化されていない接続は ws://、暗号化された接続は wss:// となり、WebSocket インスタンスでは、このパターンを使用します。 new WebSocket() メソッドで作成します。

var ws = new WebSocket(url, [protocol] );

最初のパラメータであるurlは、接続のURLを指定します。2番目のパラメータであるprotocolは、オプションで、許容されるサブプロトコルを指定します。

3.2. WebSocketのプロパティ

ws オブジェクトが生成されると、readyState が ws インスタンスの状態となり、次の 4 つの状態があります。

0 は接続が確立されていないことを意味します。

1 接続が確立され、通信可能な状態であることを示す。

2 接続が切断処理中であることを示す。

3 接続が終了しているか、接続を開くことができないことを示す。

ヒント メッセージを送信する前にステータスを判断し、切断された場合の再接続メカニズムが必要です。

3.3. WebSocketイベント

wsインスタンスオブジェクトを生成すると、以下のようなイベントが発生し、その状態に応じて、イベントコールバックにメソッドを記述することができるようになります。

  • ws.onopen 接続確立時に発生
  • ws.onmessage クライアントがサーバーからデータを受信したときに起動される
  • ws.onerror 通信エラーが発生したときに発生する。
  • ws.onclose 接続が閉じられたときに発生する
ws.onmessage = (res) => {
  console.log(res.data);
};

ws.onopen = () => {
  console.log('OPEN...') ;
};

ws.onclose = () => {
 console.log('CLOSE...') ;
}

3.4. WebSocketのメソッド

  • ws.send() 接続を使用してデータを送信します (プレーンテキストデータのみ送信可能)
  • ws.close() は、接続を閉じます。

4、デモデモ

WebSocketのAPIをある程度理解したら、鉄が熱いうちに小さなケースを実行させる。

4.1. Nodeサーバーサイド

WebSocketプロトコルは、2つの理由からNodeと非常にうまく動作します。

1. WebSocketクライアントサイドイベントベースのプログラミングは、Nodeのカスタムイベントとほとんど同じです。

2. WebSocketは長いクライアント・サーバ接続を実装しており、Nodeの基本的なイベント駆動型アプローチは高い並行性接続に適している

以下のように、webSocket.jsを作成します。

const WebSocketServer = require('ws').Server;
const wss = new WebSocketServer({ port: 8080 });
wss.on('connection', function (ws) {
    console.log('client connected');
    ws.on('message', function (message) {
        ws.send('I received' + message);
    });
});

Windowsのコマンドウィンドウを開き、以下を実行します。

4.2. HTMLクライアント

新しいindex.htmlページを作成する

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>webSocketSmallDemo</title>
</head>
<body>
    <div class="container">
        <div>
            <input type="text" id="msg">
            <button onclick="sendMsg()">Send message</button>
        </div>
    </div>
    <script>
        const ws = new WebSocket('ws://localhost:8080');
        ws.onmessage = (res) => {
            console.log(res);
        };
        ws.onopen = () => {
            console.log('OPEN...') ;
        };
        ws.onclose = () => {
            console.log('CLOSE...') ;
        }
        function sendMsg() {
            let msg = document.getElementById('msg').value;
            ws.send(msg);
        }
    </script>
</body>

ブラウザを開き、1,2,3の文字を順番に入力し、メッセージ本文の送信をクリックするたびに、送信したメッセージがws.onmessageイベントのres.dataに返されます。

5. 質問とまとめ

以上、WebSocket APIの概要と簡単な使い方を紹介しました。チャットルームのような高い同時実行性と長い接続を扱う場合は、WebSocket http リクエストの方がより適切で効率的であると思われます。

しかし、WebSocketを使う過程で、切断しやすいなどの問題があることがわかり、各メッセージを送る前に切断するかどうかを判断する必要があったり、複数のメッセージを送る場合、サーバーから返ってくるデータの量が異なるため、クライアントに返す前後の順番が異なり、前のメッセージで返ってきたデータをクライアントが受け取った後に次のメッセージを送る必要があったり、コールバックが過剰にネストしないよう Promise, async, awaitなどの同期をとる方法で解決できることがわかったりしました。WebSocketはここまで、不備があればもっと訂正を歓迎します

今回書いたのはここまでです。勉強になれば幸いです。そして、Scripting Houseを応援していただければ幸いです。