blog

ポーリング&SSE&ウェブソケット

背景ユーザーが手動でページを更新することなく、バックグラウンドで発生した変更を積極的にリアルタイムでブラウザに送信する必要性例:チャットルーム、リアルタイム見積もりシステム、オンラインゲームhttp欠...

Jan 21, 2021 · 4 min. read
シェア

背景

  • バックグラウンドで発生した変更を、ユーザーが手動でページを更新することなく、能動的にリアルタイムでブラウザに配信する必要性。
  • 例:チャットルーム、リアルタイム見積システム、オンラインゲーム
  • httpの欠陥:通信はクライアントによってのみ開始可能

polling

ポーリングとは、クライアントとサーバーの間の接続のことです。

  • サーバー時刻のリアルタイム表示
<body>
 <div>
  
 </div>
 <div class = "clock"></div>
 <script>
 function getTime() {
 let xhr = new XMLHttpRequest()
 xhr.open('get', '/polling')
 xhr.onload = () => {
 let content = xhr.response
 let clock = document.querySelector('.clock')
 clock.innerText = content
 }
 xhr.send()
 }
 getTime()
 setInterval(getTime, 1000)
 </script>
</body>
const Koa = require('koa')
const serve = require("koa-static");
const Router = require("koa-router");
// 時刻のフォーマット
const moment = require('moment')
const app = new Koa()
const router = new Router()
app.use(serve(__dirname + '/static'))
router.get('/polling', (ctx) => {
 ctx.body = moment().format()
})
app.use(router.routes())
app.listen(8080, () => {
 console.log('open 8080')
})

長所

実装が簡単で、多くの変更を加える必要がありません。

デメリット

  • ポーリング間隔が長すぎると、ユーザーは更新されたデータをタイムリーに受け取ることができません。
  • ポーリング間隔が短すぎると、クエリーリクエストが多くなり、サーバー側の負担が増えます。

SSE Server-Sent Events

実装原理

  • サーバーはクライアントに、次に送信するのはストリーム・メッセージであると宣言します。
  • 長いダウンロードをストリーミングメッセージとして完了します。
  • ストリーミング情報
    • 1回限りのパケットではありません
    • 継続的に送信する必要があるデータのストリームです。
    • クライアントは接続を閉じずに待機

長所

  • 既存のサーバーソフトウェアでサポートされているHTTPプロトコルを使用します。
  • 軽量で使いやすい
  • デフォルトで切断と再接続をサポート
  • 送信されるメッセージの種類のカスタマイズをサポート

サーバー時刻のリアルタイム表示

EventSource

<body>
 時刻表示
 <div class="block"></div>
 <script>
 // 共通アドレスの共有& ip 先頭アドレスを書く必要がない
 const eventSource = new EventSource("/sse");
 eventSource.addEventListener("open", (e) => {
 console.log("open");
 console.log(e);
 });
 eventSource.addEventListener("message", (e) => {
 console.log("message");
 console.log(e);
 document.querySelector('.block').innerText = e.data
 });
 eventSource.addEventListener("sock", (e) => {
 console.log("sock");
 console.log(e);
 document.querySelector('.block').innerText = e.data
 });
 eventSource.addEventListener("error", (e) => {
 console.log("error");
 console.log(e);
 });
 </script>
 </body>
const http = require("http");
const fs = require("fs");
const moment = require("moment");
const server = http.createServer((req, res) => {
 // fs
 // インターフェース
 if (req.url === "/sse") {
 // イベントストリームに設定する必要がある
 res.setHeader("content-type", "text/event-stream");
 // 固定フォーマットのデータ: xxxxx


 setInterval(() => {
 // トリガーするものを指定する
 res.write("event: sock
")
 //  
 このデータが終了したことを示し、上段と下段が1つのデータであることを示す
 res.write(`data: ${getDate()}

`);
 }, 1000);
 // 終了を書かないこと
 // sse
 } else {
 // 静的サービス
 const readStream = fs.createReadStream("./static/index.html");
 readStream.pipe(res);
 }
});
function getDate() {
 return moment().format("MMMM Do YYYY, h:mm:ss a");
}
server.listen(3000);

websocket

特徴

  • 二重通信
  • クロスドメインの許可
  • TCPで構築
  • 持続的接続を確立するには、httpハンドシェイクを1回行うだけです。
  • データフォーマットは比較的軽量で、パフォーマンスのオーバーヘッドが少なく、効率的な通信が可能です。
  • テキストまたはバイナリデータを送信できます。
  • 同一オリジン制限なし
  • プロトコル識別子はws

デメリット

  • 互換性の問題

プロトコルのアップグレード

Read next

FlutterのiOSとandroidプロジェクトのデフォルト言語を設定する。

1.プロジェクトのルートディレクトリの下にあるiOSまたはandroidディレクトリを削除します 2.プロジェクトのルートディレクトリにcdします flutter create -i objc を実行します . flutter create -a java を実行します。 flutter create -i objc -a java を実行します。 3. 言語をリセット...

Jan 20, 2021 · 1 min read