2011|08|
2013|10|11|12|
2014|01|02|03|04|05|06|07|08|09|10|11|12|
2015|01|02|03|05|06|07|08|09|10|11|12|
2016|01|03|04|05|06|07|08|09|10|11|12|
2017|01|02|03|04|05|06|07|08|09|10|11|12|
2018|01|02|03|04|05|06|07|08|09|10|11|12|
2019|01|02|03|04|05|06|07|08|09|10|11|12|
2020|01|02|03|04|

2020-01-02 GOによる簡単なWebSocketサーバの作り方 [長年日記]

GOによる簡単なWebSocketサーバの作り方

GOによる簡単なWebSocketサーバの作り方

  • 初版 2020/01/01 

     /home/kobore/www/soft/wstest32に一式あり

    1.目的

    • ラズパイを使って、クライアントで同じ画像の表示をさせたい
    • WebSocketを使ってクライアン間で共有させることを考えた

    2.課題

    • サンプルプログラムを見ても、(私には)仕組みが良く分からない
    • チャットアプリの例は沢山あるが、画像を共有する方法は分からなかった(多分あると思う)
    • が、まっとうな方法が分からなかったので、サンプルプログラムを流用させて貰うことにした

    3.前提

    • ラズパイにgoをインストールしておく
      • ネットに沢山が記載がある
    • "GOによる簡単なWebサーバの作り方"を作っておく
    • http://www.kobore.net/diary_techno/?date=20200101
    • go get github.com/gorilla/websocke
    • touch websocket-server.go
    • touch index.html

    4.サーバプログラム

    • https://qiita.com/__init__/items/08cbc3a870178fd6fc32 の内容と同じ
    • "./websocket-server.go"
      • package main
      • import (
        • "log"
        • "net/http"
        • "github.com/gorilla/websocket"
      • )
      • // WebSocket サーバーにつなぎにいくクライアント
      • var clients = make(map[*websocket.Conn]bool)
      • // クライアントから受け取るメッセージを格納
      • var broadcast = make(chan Message)
      • // WebSocket 更新用
      • var upgrader = websocket.Upgrader{}
      • // クライアントからは JSON 形式で受け取る
      • type Message struct {
        • Message string `json:message`
      • }
      • // クライアントのハンドラ
      • func HandleClients(w http.ResponseWriter, r *http.Request) {
        • // ゴルーチンで起動
        • go broadcastMessagesToClients()
        • // websocket の状態を更新
        • websocket, err := upgrader.Upgrade(w, r, nil)
        • if err != nil {
          • log.Fatal("error upgrading GET request to a websocket::", err)
        • }
        • // websocket を閉じる
        • defer websocket.Close()
        • clients[websocket] = true
        • for {
          • var message Message
          • // メッセージ読み込み
          • err := websocket.ReadJSON(&message)
          • if err != nil {
            • log.Printf("error occurred while reading message: %v", err)
            • delete(clients, websocket)
            • break
          • }
          • // メッセージを受け取る
            • broadcast <- message
        • }
      • }
      • func main() {
        • // localhost:8080 でアクセスした時に index.html を読み込む
        • http.HandleFunc("/", func(w http.ResponseWriter, r *http.Request) {
          • http.ServeFile(w, r, "index.html")
        • })
        • http.HandleFunc("/chat", HandleClients)
        • err := http.ListenAndServe(":8080", nil)
        • if err != nil {
          • log.Fatal("error starting http server::", err)
          • return
        • }
      • }
      • func broadcastMessagesToClients() {
        • for {
          • // メッセージ受け取り
          • message := <-broadcast
          • // クライアントの数だけループ
          • for client := range clients {
          • // 書き込む
            • err := client.WriteJSON(message)
            • if err != nil {
              • log.Printf("error occurred while writing message to client: %v",
        • err)
          • client.Close()
          • delete(clients, client)
          • }
          • }
          • }
      • }
    • 起動方法
      • go run websocket-server.go

    5.クライアントプログラム

    • こっちの方は、https://qiita.com/__init__/items/08cbc3a870178fd6fc32 の内容にちょっと追加をする
    • まったく美しくない方法だが(本来ならWebSocketを使うべき)、もうなにふり構わない
    • "./index.html"
      • コード
        • <!DOCTYPE html>
          • <head>
            • <meta charset="UTF-8">
            • <meta name="viewport" content="width=device-width, initial-scale=1.0">
            • <meta http-equiv="X-UA-Compatible" content="ie=edge">
            • <title>WebSocket Server</title>
          • </head>
          • <body>
            • <input id="input" type="text" />    <!-- 入力文字を表示  -->
            • <button onclick="send()">Send</button><!-- ボタンのメソッドをボタン本体を表
        • 示  -->
          • <pre id="output">outputのエリア</pre><!-- 出力結果を表示  -->
          • ~ <img id="image_place" src="http://192.168.0.88:8686/image3.jpg"/>
          • <script>
            • var input = document.getElementById('input');
            • var output = document.getElementById('output');
            • var socket = new WebSocket("ws://" + window.location.host + "/chat");
            • // 江端追記
            • // img要素を取得する
            • var img = document.getElementById("image_place");
            • // 表示する画像番号
            • var idx = 1;
            • // 江端追記ここまで
            • socket.onopen = function() {
            • // output.innerHTML += "Connection OK\n";
            • };
            • socket.onmessage = function(e) {
            • // output.innerHTML += "Get message from server: " + e.data + "\n";
            • // 江端追記
            • idx++;
            • if (idx > 3) {
            • idx = 1;
            • }
            • //output.innerHTML += idx + "\n";
            • //output.innerHTML += "before\n";
            • // img要素のsrcに画像ファイル名を設定する
            • //img.src = "image" + idx + ".jpg";
            • ~ img.src = "http://192.168.0.88:8686/image" + idx + ".jpg";
            • //output.innerHTML += "after\n";
            • // 江端追記ここまで
            • };
            • function send() {
              • socket.send(JSON.stringify(
              • {
                • message: input.value
              • }
              • ));
              • input.value = "";
            • };
          • </script>
          • </body>
        • </html>
      • 起動方法
        • http://192.168.0.88:8080/

    6.その他

    • 画像の場所
      • "./static/image1.jpg
        • 起動方法
          • http://192.168.0.88:8686/image1.jpg
      • "./static/image2.jpg
        • 起動方法
          • http://192.168.0.88:8686/image2.jpg