背景
- バックグラウンドで発生した変更を、ユーザーが手動でページを更新することなく、能動的にリアルタイムでブラウザに配信する必要性。
- 例:チャットルーム、リアルタイム見積システム、オンラインゲーム
- 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
デメリット
- 互換性の問題