とほほのWebSocket入門
目次
WebSocketとは
- WebSocket はサーバ・クライアント間で双方向の非同期通信を実現する技術です。
- 通常の HTTP/HTTPS では通常はクライアントからサーバに要求して応答を得るのみで、サーバからクライアントに非同期に通信するには、Server push、Long polling, Comet などを用いて疑似的に実現していましたが、いずれも短所がありました。WebSocket はこれらの短所を補う目的で開発されました。
- HTTP/HTTPS とは厳密には異なるプロトコルですが、既存の HTTP/HTTPS プロキシやロードバランサ等を経由して動作するように設計されています。
- Webチャットで誰かが書き込みを行った際に即座にクライアントに通知したり、Webコンソール機能など、サーバからクライアントにデータをプッシュする技術のひとつとして利用されています。
- URLスキーマとして
ws://または、暗号化されたwss://を用います。
サンプル(ws)
Node.js と ws を用いたサンプルを作成します。まず npm で ws をインストールします。
$ sudo npm install ws
サーバプログラム(chat-ws.js)を次のように作成します。
var server = require("ws").Server;
var s = new server({port:5000});
s.on("connection", (ws) => {
ws.on("message", (msg) => {
console.log("Recv: " + msg);
s.clients.forEach((client) => {
console.log("Send: " + msg);
client.send(msg.toString());
});
});
ws.on("close", () => {
console.log("Closed.");
});
});
node コマンドで実行します。
$ node chat-ws.js
クライアントプログラムを下記の様に作成し、ブラウザで表示します。ws://127.0.0.1:5000/ は適切なサーバアドレスに書き換えてください。
<pre id="out"></pre>
<input type="text" id="msg">
<input type="button" id="btn" value="OK">
<script>
var out = document.getElementById("out");
var msg = document.getElementById("msg");
var btn = document.getElementById("btn");
var sock = new WebSocket("ws://127.0.0.1:5000/");
sock.addEventListener("open", (e) => {
console.log("Connected.");
});
sock.addEventListener("close", (e) => {
console.log("Closed.");
});
sock.addEventListener("error", (e) => {
console.log("Error.");
});
sock.addEventListener("message", (e) => {
out.innerText += e.data + "\n";
msg.value = "";
msg.focus();
});
btn.addEventListener("click", (e) => {
sock.send(msg.value);
});
msg.focus();
</script>
入力欄のテキストを送信し、入力欄の上部に表示されれば成功です。複数のブラウザでアクセスすると、各々のブラウザ画面にメッセージを一斉配信することができます。
サンプル(Socket.IO)
同様のものを、Node.js, express, Socket.IO を用いたサンプルを示します。まず必要なパッケージをインストールします。
# npm install express # npm install socket.io
サーバ側プログラムを chat-io.js として作成します。
const app = require("express")();
const http = require("http").createServer(app);
const io = require("socket.io")(http);
app.get("/", (req, res) => {
res.sendFile(__dirname + "/index.html");
});
io.on("connection", (socket) => {
console.log("Connected.");
socket.on("post_message", (msg) => {
io.emit("recv_message", msg);
});
});
http.listen(5000, () => {
console.log("Listen start.");
});
クライアント側を index.html として chat-io.js と同じフォルダに置きます。
<!doctype html>
<html lang="ja">
<head>
<title>Socket.IO chat</title>
<script src="https://cdn.socket.io/4.4.1/socket.io.min.js"
integrity="sha384-fKnu0iswBIqkjxrhQCTZ7qlLHOFEgNkRmK2vaO/LbTZSXdJfAu6ewRBdwHPhBo/H"
crossorigin="anonymous"></script>
</head>
<body>
<pre id="out"></pre>
<input type="text" id="msg">
<input type="button" id="btn" value="OK">
<script>
var out = document.getElementById("out");
var msg = document.getElementById("msg");
var btn = document.getElementById("btn");
var socket = io();
btn.addEventListener("click", (e) => {
socket.emit("post_message", msg.value);
});
socket.on("recv_message", (message) => {
out.innerText += message + "\n";
msg.value = "";
msg.focus();
});
</script>
</body>
</html>
下記の様に起動します。
$ node chat-io.js
ブラウザから http://(サーバアドレス):5000/ にアクセスし、入力欄に記入した文字列を送受信できれば成功です。
ws と Socket.IO の違い
WebSocketはブラウザに標準で組み込まれていますが、Socket.IOはライブラリを読み込む必要があります。wsはWebSocketを利用しますが、Socket.IOはWebSocket以外にAJAX Long Polling、AJAX MultipartStreamなどにも対応します。wsが全クライアントに送信するにはクライアントの台数分ループを回す必要がありますが、Socket.IOは1回の操作で全クライアントに送信することができます。wsはデータをそのまま送信しますが、Socket.IOはsocket.emit()の第1引数にイベント名をつけて送信することができます。
関連リンク
- WebSocket API (MDN)
- ws
- Socket.IO
Copyright (C) 2022 杜甫々
初版:2022年1月23日 最終更新:2019年1月23日
https://www.tohoho-web.com/ex/websocket.html