【初心者向け】Express(Node.js)でSocket.ioを使ったチャットアプリの構築
node.jsのサーバー機能を使ったチャットアプリの作成についてのメモ書きです。フレームワークにexpressを使い、socket.ioにて双方向通信します。
socket.ioというのは簡単に言うとWebSocket 周りの技術を、Node.jsからサクッと簡単に使えるようにしたモジュールです。
目次
使用環境
- OS: Ubuntu 20.04 / エディタ: Visual Studio Code (v1.95.3)
- node.js : v18.17.1 / express : v4.21.1
- socket.io : v4.8.1 (※ npm install socket.io)
- jQuery (v1.12.4)
サーバーの構築
Expressを使ったサーバーを構築します。node.jsはインストール済とします。適当なフォルダを作りそこに移動してから、以下のコマンドを実行します。
npm init
npm install express nodemon socket.io
nodemonは開発時において、プログラム修正すれば自動でサーバーを再起動かけてくれる便利なモジュールです。無くても動作しますが、一応インストールします。
フォルダ直下に「public」-「css」-"style.css"ファイルを作りここでスタイルを決めます。また、同じ直下にクライアント側で表示する"index.html"ファイルを作成します。
フォルダ構成
Node.jsフォルダ構成
サーバー
"server.js"にコード実装してローカルサーバーを立ち上げていきます。
server.js
const express = require("express"); // ←expressモジュールを呼び出す
const app = express(); // ←インスタンス化のような感じ
const PORT = 3001; // ← ローカルで起動するport番号を指定
これでexpressフレームワークが使えるようになります。次にsocket.ioを使えるようにします。
server.js (続き-1)
const http = require("http"); // ←httpモジュール呼び出し
const server = http.createServer(app); // ←appを引数にcreateServerを作成
const socketIo = require("socket.io"); // ←socket.ioモジュールを呼び出す
const io = socketIo(server) // ←socket.ioの引数にcreateServerを渡す
これでsocket.ioも使えるようになりまたので、サーバーを起動してここまでで問題ないか確認しましょう。server.jsの最後の行に次の待ち受けコマンドを記述します。
server.js (待ち受け)
// appでなくてserverの方を待受状態にします。
server.listen(PORT, ()=>{
console.log("server is running !!"); // この表示がターミナルで確認できればOKです
});
静的ファイル(CSSファイル、JavaScriptファイル、画像など)の置き場所を、Express標準で実装されているexpress.static ミドルウェア関数を使って指定します。ここではpublicフォルダを作成してそこに置く構成とします。
server.js (ルーチング設定)
app.use(express.static(__dirname + '/public'));
app.get('/chat', (req,res)=>{
res.sendFile(__dirname + "/index.html");
});
socket.ioで使う関数
サーバー側ではクライアント側の接続を受け付けると, io.socketsオブジェクトにconnectionイベントが発生します。使い方は、次の通りです。
io.socket.on(eventname, callback(socketオブジェクト){
})
callback関数の引数としてsocketオブジェクトを受け取ることができます。socketオブジェクト名は何でも良いのでここではsocとします。
クライアントからの受信はsoc.on()で受け、クライアントへの送信はio.sockets.emit()メソッドを使用します。ただこのメソッドは、接続しているソケット全てに送信するメソッドになります。
大雑把に言うとonが付けば受信待ちを表し、emitが付けば送信を表します。
io.sockets.emit('server chanel', data.msg)の第1引数は'イベント名'で自由に付けて良く、このイベント名で打2引数のデータを送受信します。(※'server chanel'などのイベント名は、送受信間の紐づけをしますので、間違わないように気をつけてプログラミングしてください。)
従ってクライアントからの送信メッセージは全て、接続している人全員で確認できる簡易チャットとなります。
server.js (socket通信部分)
let counter = 0; //接続数のカウンタ
io.sockets.on('connect', (soc)=>{
counter ++;
console.log(`ユーザーが接続しました。 合計 ${counter} 人です`);
// --->受信(※後の説明にありますがクライアントはobject形式で送信)
soc.on('client chanel', (data)=>{
// <---送信(※object形式で返信)
// io.sockets.emit()は接続しているソケット全てに送信します。
io.sockets.emit('server chanel', data.msg ); // ...①
});
// 切断
soc.on('disconnect', ()=>{
counter--;
console.log(`合計${counter}人に減りました。`);
});
});
クライアントの構築
jQueryの準備
jQueryをインストールしても良いですが、簡単なCDNを貼り付ける形で検討します。CDNはjQueryの公式サイトやGoogleがホストしているサイトなどから入手できます。どちらからでも問題ありませんが、ここでは大手のGoogleから出しているCDNを利用しました。
もちろんJavaScriptだけで実装しても大丈夫です。
クライアントの実装
<script src="/socket.io/socket.io.js"></script>の記述を忘れないようにします。このファイルを別途作る必要はなく、server.jsでsocket.ioと立ち上げておいて、リクエストが来たときに自動生成されるようなので、取り敢えずそう書いておきます。そうすると、以降でioオブジェクトが使えるようになります。
- const socket = io.connect(); ←サーバー側と接続するコマンド
- socket.emit() ←サーバー側にデータを送信
- socket.on() ←サーバー側からのデータ待ち受け状態
index.html
<!DOCTYPE html>
<html lang="ja">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>SocketIoのテスト</title>
<link rel="stylesheet" type="text/css" href="/css/style.css">
</head>
<body>
<div class="container">
<h2>Express チャットアプリ</h2>
<ul class="chatboard" id="chat_msg">
</ul>
<form id="socket_form" class="send_form">
<label>message</label> <input type="text" id="msg">
<button type="submit" class="submit-btn">送信</button>
</form>
</div>
<script src="https://ajax.googleapis.com/ajax/libs/jquery/1.12.4/jquery.min.js"></script>
<script src="/socket.io/socket.io.js"></script>
<script>
$(function(){
const socket = io.connect();
/*************************************
* formがsubmitされたときの処理
* この中でデータを送信する
**************************************/
$("#socket_form").on("submit",(e)=>{
e.preventDefault();
if ($('#msg').val()){
socket.emit('client chanel',{ // ※送信
msg : $('#msg').val(),
});
$('#msg').val('').focus();
}
});
/*************************************
* サーバーからの受信待ち処理
* この中でデータを受信する
**************************************/
socket.on('server chanel', (data)=>{ // ※受信
// 受信
let $li = $("<li></li>");
$li.text(data);
$("#chat_msg").append($li);
})
});
</script>
</body>
</html>
動作結果
一斉配信(自分にも配信)
配信に"io.sockets.emit()"メソッドを使います。
一斉送信
io.sockets.on('connect', (soc)=>{
// ---受信
soc.on('client chanel', (data)=>{
// ---接続しているソケット全てに送信
io.sockets.emit('server chanel', data.msg);
});
});
全員に配信する例
接続者全員に送信する。
broadcast配信(自分以外)
配信に"soc.broadcast.emit()"メソッドを使います。
接続しているソケット全てに送信
io.sockets.on('connect', (soc)=>{
// ---受信
soc.on('client chanel', (data)=>{
// サーバーに接続されているすべてのソケットにイベントを送信)
soc.broadcast.emit('server chanel', data.msg);
});
});
自分以外の人全員に配信
自分には配信されません
以上です。