今回は、WebSocketによる双方向通信を簡単に記述できる「Socket.io」の基本的な使い方から簡単なチャットアプリの作り方までを学習していきましょう!
「Socket.ioって何?どうやって使うの?」
「チャットアプリを自作したい」
「双方向通信によるメッセージの送受信方法が知りたい」
このような内容も含めて、本記事では以下のような構成で解説していきます!
【基礎】「Socket.io」の使い方
【実践】Socket.ioによるフロントサイド
【実践】Socket.ioによるサーバーサイド
この記事で、Socket.ioをしっかり学習してスキルアップを目指していきましょう!
「Socket.io」とは?
まずは、「Socket.io」の概要から見ていきましょう!
Socket.ioはWebSocket技術によるデータの双方向通信を強力にサポートしてくれるサービスとして公開されています。
基本的に、Socket.ioを使わなくてもWebSocketによる双方向通信はプログラミング可能なのですが、ブラウザの種類やユーザーのPC環境などによって接続されないことが多いのです。
※Socket.ioを使わないWebSocketによる双方向通信のチュートリアルはこちら
https://www.sejuku.net/blog/70583
これを安定させようとすると、深い知識と経験が必要となり初心者は途方に暮れてしまうでしょう。
このようなケースを想定して安定かつ簡潔に双方向通信をプログラミングできるように公開されているのが、今回学習する「Socket.io」なのです。
ユーザー環境に合わせた安定接続のための高度な処理はすべてSocket.ioにまかせることで、我々は作りたいものに集中できるというわけです。
「Socket.io」の使い方
この章では、「Socket.io」の基本的な導入や使い方について見ていきましょう!
主に、Socket.ioをインストールする手順と最小限のサーバーを構築するところまでを学習します。
Socket.ioのインストールと準備
まずは、Socket.ioを利用するためにNode.js用のパッケージをインストールするところから始めましょう!
コマンド自体はシンプルで、npmからinstallコマンドを実行することで導入は完了します。
npm install --save socket.io
あとは、require()でNode.jsから扱えるようにするだけなのですが、ポイントはサーバーオブジェクトを設定するという点です。
var io = require('socket.io')(【サーバーオブジェクト】);
サーバーオブジェクトは簡単に言うとNode.jsで構築されたサーバーのことなのですが、一般的にはhttpモジュールを使う方法とExpressを使う方法があります。
詳しくは次の章から見ていきましょう!
httpモジュールによるサーバーの構築方法
まずは、最も基本となるhttpモジュールを利用したサーバーを構築してみましょう!
今回はチャットアプリで利用する「index.html」を表示するだけのシンプルなサーバーにしてみます。
var http = require('http').createServer(handler); var html = require('fs').readFileSync('views/index.html'); function handler(request, response) { response.writeHead(200, {'Content-Type': 'text/html'}); response.end(html); } http.listen(3000);
この例では、createServer()メソッドの引数にindex.htmlファイルを表示する関数を設定していますね。
readFileSync()を利用することでサーバーにアップロードされているファイルを取得し、それを「handler()」関数を経由してブラウザに出力するという流れです。
httpモジュールを使ったサーバーの構築方法に不安がある方は、次の記事で基本から応用までをまとめているので参考にしてみてください!
また、サーバーが構築できたらSocket.ioの引数へサーバーオブジェクトを指定するのを忘れないようにしましょう!
var io = require('socket.io')(http);
Expressによるサーバーの構築方法
次に、定番のフレームワークとしてよく使われるExpressによるサーバー構築を見ていきましょう!
まずは、ExpressをNode.jsから扱えるようにするためにrequire()を記述しておきます。
var express = require('express'); var app = express();
そして、createServer()の引数に先ほど作成したExpressのサーバーオブジェクトを設定します。
var server = require('http').createServer(app); app.get("/", function (request, response) { response.sendFile(__dirname + '/views/index.html'); }); server.listen(3000);
get()メソッド内にindex.htmlのファイルパスを記述するだけで、シンプルなサーバー構築を実現できるので便利ですね。
ポイントは、通常のapp.listen()ではなくserver.listen()を利用するという点を忘れないようにしましょう。
最後に、Socket.ioの引数にもサーバーオブジェクトを設定しておきましょう!
var io = require('socket.io').listen(server);
Expressを利用すると記述が簡潔になるので便利ですね。
ちなみに、Expressの基本的な使い方を体系的に学べるように次の記事で解説しているので合わせて学習してみることをオススメします!
「Socket.io」のフロントサイド
この章では、「Socket.io」を利用したフロントサイドのプログラミングについて見ていきましょう!
主に、チャットフォームの設置やメッセージの送受信について学んでいきます。
チャットフォームの作り方
まずは、Webブラウザに表示されるチャットアプリの画面から作っていきましょう!
今回作るチャットアプリは、以下のように最小限の構成で構築されたシンプルなものになります。
この画面を作るために、まずは最低限の画面デザインを構築できる「Milligram.css」を導入しておきましょう。
Milligram.cssは特にクラス名などを付与しなくても、一般的なHTMLタグをそのまま記述するだけで見た目の良いデザインに変えてくれるスグレモノです。
あとは、HTMLで以下のようなフォームを作りましょう。
「form」の中身は単純な入力ボックスとボタンが配置されているだけです。
下段には「ulタグ」でチャットのメッセージをすべて一覧で出力するようにしてみましょう。
メッセージをサーバーに送信する方法
それでは、フロント側からサーバーへ任意のメッセージを送信する方法を見ていきましょう!
まず最初にフロント側でSocket.ioが扱えるようにするため、次のようにJavaScriptライブラリを読み込んでおきます。
そのあとに、「io()」を任意の変数へ格納することでSocket.ioが提供するさまざまなAPIを利用することができるのです。
var socket = io(); var message = document.getElementById('message'); var form = document.forms.myform;
ついでに、ulタグにメッセージを出力するために要素を取得するのと、フォームへアクセスするための記述も上記のとおり設定しておきましょう。
あとは、フォームのボタンがクリックされたタイミングで入力ボックスに記述されたテキストを取得し、サーバーへ送信する処理を作れば良いですね。
任意のテキストを送信する場合は「emit()」メソッドを次のように利用します。
form.btn.addEventListener('click', function(e) { e.preventDefault(); socket.emit('chat', form.text.value); form.text.value = ''; })
この例では、フォームのボタンがクリックされたタイミングでemit()を実行してテキストを送信しています。
ポイントはemit()の第1引数の「chat」という文字列で、これは何でも良いのですがサーバー側の処理も同じ文字列を利用する必要があります。
イメージとしては、同じ文字列をフロント・サーバー両方で使用することで同じ空間を共有するようなニュアンスがあります。
ちなみに、「e.preventDefault()」はフォームの画面更新をキャンセルする処理で、「form.text.value=”」は入力ボックスを空っぽにするという意味です。
サーバーからのメッセージを取得して表示する方法
フロント側からメッセージをサーバーへ送信すると、今度はサーバーから全ユーザーに向けて送られてきた文字列を配信します。
これにより、チャットアプリにアクセスしているすべてのユーザーが同じメッセージを共有して閲覧することができるわけですね。
そこで、サーバーから送信されたメッセージを取得してブラウザの画面に表示する処理を作らなければいけません。
これを実現するにはon()メソッドを次のように記述します。
socket.on('chat', function(msg){ //ここに処理を記述する });
第1引数には今回利用している「chat」という文字列を使い、第2引数に実行したい関数処理を記述します。
関数の引数「msg」には、サーバーから送られたメッセージ(文字列)が格納されています。
そこで、次のように記述すればサーバーからのメッセージを画面に出力することができますね!
socket.on('chat', function(msg){ var li = document.createElement('li'); li.textContent = msg; message.appendChild(li); });
この例では、li要素を作成してそこにサーバーから取得した文字列を組み込んでいます。
appendChild()でulタグの中に配置することで、次々とチャットのメッセージが一覧表示で閲覧することができるわけです。
「Socket.io」のサーバーサイド
この章では、「Socket.io」を利用したサーバー側の処理を見ていきましょう!
主に、フロントからのメッセージを取得・配信する方法について学んでいきます。
メッセージを取得・配信する方法
それでは、フロント側から送信されたメッセージを取得する処理を作っていきましょう!
これを実現するには、まず最初にon()メソッドを使ってフロント側と接続されているかを確認します。
io.on('connection', function(socket){ //ここに処理を記述する });
第1引数に「connection」を設定することで、接続されているかどうかを確認できます。
接続されている場合は、第2引数の関数を実行することができます。
この関数の引数「socket」に、ユーザー情報も含めて送信されたメッセージが格納されています。
そこで、このsocketを使ってon()メソッドを次のように記述してみましょう!
io.on('connection', function(socket){ socket.on('chat', function(msg){ console.log(msg); }); });
この例では、第1引数にフロント側と同じ文字列「chat」を設定し、第2引数の関数内で取得したメッセージをコンソールに出力しています。
このようにフロント側のメッセージを取得できるので、emit()を次のように実行すれば全ユーザーにメッセージを配信することもできるのです。
io.on('connection', function(socket){ socket.on('chat', function(msg){ io.emit('chat', msg); }); });
このように記述することで、メッセージを送信した瞬間にサーバーからメッセージが配信されて画面に表示されるわけです。
もちろん、複数人がアクセスしている場合はすべてのユーザーにメッセージが表示されるようになっています。
ユーザーを判別する方法について
すでにこの時点で、チャットアプリの基本動作はできるようになっています。
しかしながら、誰がどのメッセージを送信したのか分からない状態ですよね?
そこで、ユーザーを判別してメッセージの横に誰が送信したのか分かりやすいように「ユーザー名」も一緒に表示できるように改造してみましょう!
まずは、フロント側でチャットアプリにアクセスした際にユーザー名を入力する画面を表示するようにします。
socket.on('connect', function(){ socket.emit('setUserName', prompt('ユーザー名を入力してください')); });
この例では、「connect」イベント内でprompt()を使ってユーザー名を入力する処理を記述しています。
これにより、emit()を使って「setUserName」という空間で入力されたユーザー名がサーバーへ送信されます。
そして、サーバー側の処理としては送信されたユーザー名を取得して、各ユーザーを判別できるようにしておきます。
(※io.on()の「connection」内に次のコードを追記します)
socket.on('setUserName', function (userName) { if(!userName) userName = '匿名'; socket.userName = userName; });
on()メソッドを追加して「sockeet.userName」というプロパティを作り、そこへ取得したユーザー名を当てはめます。
これにより、アクセスしているユーザーの情報にユーザー名が組み込まれるので、簡単に判別できるようになります。
また、ユーザー名が何も入力されなかった時を考慮して、「if(!userName)」で分岐処理を作り「匿名」を当てはめるようにしておきましょう。
そして、メッセージを配信する際に「socket.userName」を一緒に送るようにすれば良いわけです。
socket.on('chat', function(msg){ io.emit('chat', socket.userName + ': ' + msg); });
これで、誰がどのメッセージを送信したのか分かりやすくなりましたね!
このようにSocket.ioを使うと、非常にシンプルな記述で簡単なチャットアプリが作れるわけです。
まとめ
今回は、Socket.ioの使い方と簡単なチャットアプリを作るまでを学習しました!
最後に、もう一度ポイントをおさらいしておきましょう!
・Socket.ioを利用するためのサーバー構築はhttpモジュールかExpressを使う
・フロント側では専用のライブラリを読み込みemit()を使ってメッセージを送る
・サーバー側ではon()でフロント側と接続されているかを確認して処理を行う
上記内容を踏まえて、ぜひ自分でもプログラミングに取り入れて活用できるように頑張りましょう!