[Go言語/JavaScript]WebSocketsでチャットアプリを実装!~コネクション確立編~

こんにちは。KOUKIです。
Go言語とJavaScriptでチャットアプリの作成方法を記事にしています。

前回は、簡単なWebサーバーとチャットUIを作成し、画面表示するところまで実装しました。

今回からいよいよWebSocketsを使って、チャットアプリケーションを作成していきます!

本記事では、Go言語側でWebSocketsのエンドポイントを、JavaScript側でWebsocketsオブジェクトをそれぞれ作成し、ブラウザとサーバー間で、WebSocketsのコネクションを確立します。

前回

WebSocketsのエンドポイントの作成

WebSocketsのエンドポイントを作成しましょう。

connect.go

まずは、WebSockets返却用のデータ構造体をconnect.goに実装します。

Actionには、WebSocketsへ送る命令を格納します。例えば、「ブロードキャストしろ」、とか「セッションを閉じろ」とかですね。

Messageには、ブラウザから受け取ったメッセージを格納します。

handlers.go

handlers.goには、WebSocketsのエンドポイントを実装します。

Gorilla WebSocketを使えば、割と簡単に作れます。

routes.go

先ほど作成したWebSocketsのエンドポイントをroutes.goに追加します。

これで、「ws://127.0.0.1:8080/ws」にアクセス可能になりました。

WebSocketsオブジェクトの作成

JavaScrit側で、WebSocketsオブジェクトを作成し、サーバー側と通信してみましょう。

接続に成功すれば「Successfully connected」がコンソール上に出力されるはずです。

ブラウザから「http://localhost:8080/」にアクセスし、F12でデベロッパーツールを開いて確認してみましょう。

OKですね。

サーバーからも以下のログが出力されています。

WebSocketsイベントハンドラの追加

先ほどと同じ要領で、WebSocketsイベントのハンドラを追加していきます。

WebSocketsのハンドリング

ここから少し、難しくなります。

ブラウザからリクエストを受信後、コネクションを確立しているユーザー全てにメッセージをブロードキャストする必要があるため、その為の処理を実装していきます。

新しい構造体を追加

connect.goに次の構造体を追加しましょう。

WebScoketConnectionは、WebSocketsのコネクション情報を格納するためのもです。一方、WsPayloadは、ブラウザから送信されたデータを格納します。

コネクション情報格納用の変数を宣言

チャットアプリでは、コネクション情報(ユーザーやPayload)を保持する必要があります。

そのため、handlers.goに以下の変数を宣言しましょう。

コネクション情報の保持

先ほど作成したWsEndpoint関数に、次の処理を追加します。

この後、補足にも書きますが、WsEndpointはブラウザが読み込まれた時、一度だけ呼び出されます。この時はまだユーザー名を保持していないので、「clients[conn] = “”」としています。

ちなみに、ユーザー名は、以下のボックスに打ち込んだ時にWebSockets経由でサーバーに渡す予定です。

WobSocketsリッスン関数

次にWebSocketsをリッスンする関数を作成しましょう。

この関数は、WebSocketsのエンドポイントにアクセスした時、そのコネクション情報からPayloadを読み込んで、チャネルに格納します。

そして、無限ループでずっと起動させておきます。これにより、既にコネクションが確立されている通信は、ここから情報を取得することができます。

この関数は、非同期で動作させる必要があるので、WsEndpoint関数からgoroutineを使って呼び出しましょう。

WsEndpoint関数の補足

WsEndpoint関数は、ブラウザから「http://localhost:8080/」にアクセスした時に、JavaScriptから一度だけ呼び出されます

逆にそれ以降は呼び出されないので、WebSocketsのリクエストを何らかの形で受け取る必要があります。

そこで、goroutineを使って、ListenForWs関数を別プロセスで呼び出すことで、ブラウザからの通信を常にキャッチし続ける状態を作っています。

ちなみに、goroutineを使うには関数の前に「go 」キーワードを指定するだけでOKです。

そして、ListenForWs関数のパラメータには、ポインタ(&)を使っているので、同じコネクション情報を参照します。

ブロードキャスト関数の作成

先ほど、変数として宣言したclientsには、全てのユーザー情報を格納します。

そして、チャットでは、メッセージの送信を検知したら、全てのユーザーに対してメッセージを送信する必要があります

その為、次の関数を追加しましょう。

wsChanチャネルリッスン関数

次に、wsChanチャネルをリッスンする関数を作成します。
wsChanチャネルにメッセージが格納されたら、先ほど実装したbroadcastToAll関数を使って、全てのユーザーにメッセージを送信します。

この関数は、wsChanチャネルからメッセージを読み取り、全ユーザーにメッセージをブロードキャストする性質上、Webサーバーとは別のプロセスで起動した方が良さそうです。

main関数からListenToWsChannelをgoroutineで呼び出しましょう。

動作確認

JavaScriptの以下の処理で、メッセージをブラウザのコンソールから確認できるようにしています。

アプリを起動し直して、ブラウザからメッセージが送信されてくるか確認しましょう。

OKですね。

ちなみに、ページをリロードすると次のエラーが出ますが、これで正常です。

このエラーは、ページリロード時に、コネクションを貼り直しに行くことで発生します。これにより、とあるバグが生み出されてしまいますが、次の記事で紹介したいと思います。

次回

次回も引き続き、WebSocketsを使って実装を進めていきます。

それでは、また!

Go記事まとめ

コメントを残す