WebSocketを触る機会があったのでGo言語で簡単にWebSocketを実装して動作を検証してみました。
WebSocketは、Webアプリケーションでリアルタイム通信を実現するためのプロトコルです。
WebSocketを使用することで、サーバーとクライアント間で双方向通信を行うことができます。
この記事では、Go言語を使用してWebSocketを実装する方法をチャットっぽいものを例にして紹介します。
WebSocketとは
WebSocketは、クライアントとサーバ間でのリアルタイム通信を実現するためのプロトコルです。
WebSocketを使用することで、Webアプリケーションはサーバからのイベントを受け取ったりサーバにデータを送信したりすることができます。
サーバとクライアント間で双方向通信を行うことができるため、リアルタイムでのデータの送受信が可能です。
また、WebSocketは長期間接続を維持することができるためクライアントとサーバ間でのやり取りを継続することができます。
現在ではさまざまなタイプのリアルタイムアプリケーション(例えば、オンラインゲームやチャットアプリケーション)で広く使われています。
WebSocketのクライアント側
必要箇所だけピックアップするのでソースコード全体はこちらから↓
まずはサーバーからメッセージを受け取るところから見ていきます。
window.onload = function () {
socket = new WebSocket("ws://localhost:3000/ws");
socket.onopen = function () {
updateMessage("接続できました");
};
socket.onmessage = function (event) {
// サーバーからメッセージを受け取る
updateMessage(event.data);
};
};
ページを読み込んだ際にWebSocketサーバーのURLを指定してWebSocketオブジェクトを生成します。
onopen
メソッドではWebSocket接続が開始されたときに実行されます。
onmessage
メソッドではサーバからのメッセージを受け取るたびに実行され、受け取ったメッセージを表示しています。
updateMessage
メソッドはWebページにメッセージを表示するための関数です。
次にサーバーにメッセージを送信します。
function send() {
let sendMessage = document.getElementById("message");
let msg = sendMessage.value;
if (msg == "") {
return;
}
socket.send(msg);
updateMessage(msg);
sendMessage.value = "";
}
HTMLから送信するメッセージを取得しWebSocketオブジェクトのsend
メソッドを使用して、送信するメッセージをWebSocketサーバに送信しています。
WebSocketのサーバー側
今回はgolang.org/x/net/websocket
パッケージを使った方法になります。
いろいろ調べているとgorilla/websocketを使った方法もありました。
main
メソッドから見ていきます。
var broadcast = make(chan string)
func main() {
http.HandleFunc("/", index)
http.Handle("/ws", websocket.Handler(handleConnection))
go handleMessages()
// HTTPサーバーを開始して、ポート3000でリクエストを待ち受け
err := http.ListenAndServe(":3000", nil)
if err != nil {
log.Fatal(err)
}
}
最初にブロードキャストするためのchannel宣言をしておきます。
WebSocketのルーティングを登録し、メッセージを処理するメソッドをゴルーチンで実行します。
次にhandleConnectionを見ていきます。
func handleConnection(ws *websocket.Conn) {
defer ws.Close()
// 初回のメッセージを送信
err := websocket.Message.Send(ws, "こんにちは!")
if err != nil {
log.Fatalln(err)
}
clients[ws] = true
for {
// メッセージを受信する
msg := ""
err = websocket.Message.Receive(ws, &msg)
if err != nil {
log.Fatalln(err)
}
// 受け取ったメッセージをbroadcastチャネルに送る
broadcast <- msg
}
}
クライアントとWebSocketの接続ができたらwebsocket.Message.Send
メソッドで最初のメッセージをサーバー側から送信します。
ループの中でwebsocket.Message.Receive
メソッドを使用して、WebSocket接続から新しいメッセージを受信しています。
受信したメッセージを最初に宣言しておいたbroadcast
チャンネルに送信して、他のクライアントにメッセージをブロードキャストすることができます。
最後にメッセージを処理する中身です。
func handleMessages() {
for {
// broadcastチャネルからメッセージを受け取る
msg := <-broadcast
// 接続中の全クライアントにメッセージを送る
for client := range clients {
// メッセージを返信する
err := websocket.Message.Send(client, fmt.Sprintf(`%q というメッセージを受け取りました。`, msg))
if err != nil {
log.Fatalln(err)
}
}
}
}
broadcast
チャンネルからメッセージを受信し、WebSocket接続しているクライアントに対してメッセージを送信します。
これでメッセージ送信元のクライアント以外のクライアントにもメッセージが送信されます。
挙動確認
上記コードを元にlocalhost:3000にアクセスするとWebSocketが接続されていることがわかります。
ステータスコードが101でプロトコルを切り替えたと書いていますね。
WebSocketでのチャットの挙動を確認してみます。
クライアントから送ったメッセージがサーバーで受け取って返していることがわかります。
しかし、これだと普通のHTTPでも実現可能です。
別ブラウザを2つ起動して確認してみます。
ブラウザAで送信した内容がサーバーに行き、WebSocket接続しているブラウザBにも同じ内容が送信されていることがわかります。
コメント