golang の Websocket を使用してリアルタイム マップ関数を開発する方法

WBOY
リリース: 2023-12-02 13:49:41
オリジナル
769 人が閲覧しました

golang の Websocket を使用してリアルタイム マップ関数を開発する方法

Golang の Websocket を使用してリアルタイム マップ関数を開発する方法

今日の Web アプリケーション開発では、特にリアルタイム パフォーマンスに対する要求がますます高まっています。リアルタイム マップ機能などの地理的位置に関するアプリケーション。 Golang の Websocket テクノロジーは、高速かつリアルタイムの双方向通信を提供できるため、リアルタイム マップ機能の開発に適しています。この記事では、GolangのWebsocketを使ってリアルタイムマップ機能を開発する方法を、具体的なコード例を交えながら紹介します。

1. 基本概念

1.1 Websocket

Websocket は HTML5 で導入された新しいプロトコルで、従来の HTTP プロトコル上で双方向通信を確立する技術です。 Websocket は、HTTP/HTTPS の標準ポートを使用してクライアントとサーバーの間に長い接続を確立し、サーバーがリアルタイムでデータをクライアントにプッシュできるようにします。同時に、Websocket は TCP プロトコルと同様の双方向通信もサポートしており、クライアントとサーバーが同時にデータを送信できるようになります。

1.2 Golang

Golang は、高速、効率的、安全なプログラミング言語であり、特に Web 開発に適しています。 Golang の Websocket 開発では、標準の net/http ライブラリによって提供される Websocket モジュールを使用できます。これは非常に便利で簡単です。

2. 実装手順

2.1 環境設定

まず、公式 Web サイトからダウンロードしてインストールできる Golang をインストールする必要があります。次に、コマンド ラインに次のコマンドを入力して、WebSocket モジュールをインストールします。

go get github.com/gorilla/websocket

2.2 バックエンドの実装

Golang で、次のように記述します。 Websocket サーバー側は比較的単純です。 http ライブラリの HandleFunc 関数を使用してルーターを作成し、リクエスト処理関数を指定できます。処理機能では、WebSocketライブラリのUpgrader関数を使用してHTTPプロトコルをWebSocketプロトコルに切り替え、ReadMessage関数とWriteMessage関数を使用して双方向通信を実現します。以下は簡単な例です:

package main

import (
    "log"
    "net/http"

    "github.com/gorilla/websocket"
)

func main() {
    http.HandleFunc("/", serveHome)
    http.HandleFunc("/ws", handleWebSocket)
    if err := http.ListenAndServe(":8080", nil); err != nil {
        log.Fatal("ListenAndServe: ", err)
    }
}

func serveHome(w http.ResponseWriter, r *http.Request) {
    http.ServeFile(w, r, "index.html")
}

var upgrader = websocket.Upgrader{
    ReadBufferSize:  1024,
    WriteBufferSize: 1024,
}

func handleWebSocket(w http.ResponseWriter, r *http.Request) {
    conn, err := upgrader.Upgrade(w, r, nil)
    if err != nil {
        log.Println(err)
        return
    }
    defer conn.Close()

    for {
        messageType, p, err := conn.ReadMessage()
        if err != nil {
            log.Println(err)
            return
        }
        log.Printf("Received message: %s", p)

        err = conn.WriteMessage(messageType, p)
        if err != nil {
            log.Println(err)
            return
        }
    }
}
ログイン後にコピー

2.3 フロントエンドの実装

フロントエンドでは、JavaScript を使用して Websocket 接続を確立し、send 関数を使用してサーバーに情報を送信します。 、onmessage 関数を使用して、サーバーによってプッシュされた情報を受信します。以下は簡単な例です:

var socket = new WebSocket("ws://localhost:8080/ws");

socket.onopen = function(event) {
    socket.send("Hello, server!");
};

socket.onmessage = function(event) {
    console.log("Received message: " + event.data);
};
ログイン後にコピー

3. リアルタイム マップの例

以下では、上記の 2 つの部分を結合し、Golang の Websocket テクノロジを使用してリアルタイム マップ関数を実装します。

3.1 バックエンドの実装

サーバー側では、Golang の標準ライブラリ「net/http」とサードパーティ ライブラリ「gorilla/websocket」を使用して WebSocket 通信を実装できます。具体的なコードは次のとおりです。

package main

import (
    "encoding/json"
    "flag"
    "fmt"
    "html/template"
    "log"
    "net/http"
    "sync"

    "github.com/gorilla/websocket"
)

const (
    MapWidth  = 800
    MapHeight = 600
)

var (
    port         = flag.Int("port", 8888, "http listen port")
    addr         = flag.String("addr", "localhost", "http server address")
    mu           sync.Mutex
    connections map[*websocket.Conn]bool
)

func init() {
    connections = make(map[*websocket.Conn]bool)
}

type Position struct {
    X float64 `json:"x"`
    Y float64 `json:"y"`
}

type Location struct {
    Name     string   `json:"name"`
    Position Position `json:"position"`
}

type Map struct {
    Name      string     `json:"name"`
    ImageURL  string     `json:"image_url"`
    Locations []Location `json:"locations"`
}

var (
    maps = []Map{
        Map{
            Name:     "Campus Map",
            ImageURL: "/static/campus_map.png",
            Locations: []Location{
                Location{
                    Name: "Library",
                    Position: Position{
                        X: 400,
                        Y: 300,
                    },
                },
                Location{
                    Name: "Dormitory Building",
                    Position: Position{
                        X: 300,
                        Y: 200,
                    },
                },
                Location{
                    Name: "Teaching Building",
                    Position: Position{
                        X: 500,
                        Y: 400,
                    },
                },
            },
        },
    }
)

func main() {
    flag.Parse()
    http.HandleFunc("/", indexPageHandler)
    http.HandleFunc("/ws", wsHandler)

    staticHandler := http.FileServer(http.Dir("static"))
    http.Handle("/static/", http.StripPrefix("/static/", staticHandler))

    addr := fmt.Sprintf("%s:%d", *addr, *port)
    log.Printf("Starting server on %s", addr)
    err := http.ListenAndServe(addr, nil)
    if err != nil {
        log.Fatal("ListenAndServe: ", err)
    }
}

func indexPageHandler(w http.ResponseWriter, r *http.Request) {
    indexTemplate := template.Must(template.ParseFiles("templates/index.html"))
    indexTemplate.ExecuteTemplate(w, "index.html", maps)
}

type Message struct {
    Action   string `json:"action"`
    Location string `json:"location"`
}

func wsHandler(w http.ResponseWriter, r *http.Request) {
    ws, err := websocket.Upgrade(w, r, nil, 1024, 1024)
    if err != nil {
        http.Error(w, "Could not open websocket connection", http.StatusBadRequest)
        return
    }
    defer ws.Close()

    mu.Lock()
    connections[ws] = true
    mu.Unlock()

    for {
        msgType, msg, err := ws.ReadMessage()
        if err != nil {
            delete(connections, ws)
            return
        } else {
            log.Printf("Received: %s
", msg)
            m := &Message{}
            if err := json.Unmarshal(msg, m); err != nil {
                log.Printf("Failed to unmarshal message %s: %v", msg, err)
            } else {
                switch m.Action {
                case "move":
                    sendUpdate(ws, m.Location)
                    updateMap(m.Location)
                case "logout":
                    delete(connections, ws)
                }
            }
        }

        for c := range connections {
            err = c.WriteMessage(msgType, msg)
            if err != nil {
                delete(connections, c)
                log.Printf("Error writing to user [%s]: %v
", c.RemoteAddr(), err)
            }
        }
    }
}

func updateMap(loc string) {
    for i := range maps {
        for j := range maps[i].Locations {
            if maps[i].Locations[j].Name == loc {
                maps[i].Locations[j].Position.X += 20
                maps[i].Locations[j].Position.Y += 20
            }
        }
    }
}

func sendUpdate(ws *websocket.Conn, loc string) {
    for i := range maps {
        if maps[i].Name == "Campus Map" {
            msg := &Message{
                Action: "update",
                Location: loc,
            }
            for j := range maps[i].Locations {
                location := maps[i].Locations[j]
                msgBody, _ := json.Marshal(location)
                if err := ws.WriteMessage(websocket.TextMessage, msgBody); err != nil {
                    log.Printf("Could not send message: %v", err)
                }
            }
            break
        }
    }
}
ログイン後にコピー

3.2 フロントエンドの実装

フロントエンドでは、JavaScript を使用して Websocket 接続を確立し、send 関数を使用してサーバーに情報を送信します。 、onmessage 関数を使用して、サーバーによってプッシュされたメッセージを受信します。 HTML5 ライブ マップは、SVG タグを使用して描画できます。以下に簡単な例を示します。

<!doctype html>
<html>

<head>
  <title>Realtime Map</title>

  <style>
    #map {
      width: 800px;
      height: 600px;
    }
  </style>
</head>

<body>
  <svg id="map">
    <image xlink:href="{{ .ImageURL }}" width="{{ .Width }}" height="{{ .Height }}" />
    {{ range $location := .Locations }}
      <circle id="{{ $location.Name }}" cx="{{ $location.Position.X }}" cy="{{ $location.Position.Y }}" r="5" fill="red" />
    {{ end }}
  </svg>

  <script>
    var ws = new WebSocket("ws://localhost:8888/ws");

    ws.onopen = function(event) {
      console.log("WebSocket connected");
    };

    ws.onmessage = function(event) {
      var data = JSON.parse(event.data);

      if (data.action === "update") {
        var location = data.location;
        var $circle = document.getElementById(location.name);
        var x = parseFloat($circle.getAttribute("cx"));
        var y = parseFloat($circle.getAttribute("cy"));
        $circle.setAttribute("cx", x + location.position.x);
        $circle.setAttribute("cy", y + location.position.y);
      }
    };

    window.addEventListener("load", function() {
      var $circles = document.querySelectorAll("#map circle");
      for (var i = 0; i < $circles.length; i++) {
        $circles[i].addEventListener("click", function() {
          var location = this.id;
          var msg = {
            action: "move",
            location: location
          };
          ws.send(JSON.stringify(msg));
        });
      }
    });
  </script>
</body>

</html>
ログイン後にコピー

4. まとめ

この記事では、Golang の Websocket テクノロジの基本概念を紹介した後、リアルタイム マップ関数の開発例を示します。上記の例では、HTML5 および SVG タグを通じて地図を描画し、Websocket テクノロジーを使用してリアルタイムの双方向通信を実現し、リアルタイム地図機能を実現できます。もちろん、上記は単なる例であり、実際のシナリオでは、特定のアプリケーション要件に応じて適切な改善と最適化を行う必要があります。

以上がgolang の Websocket を使用してリアルタイム マップ関数を開発する方法の詳細内容です。詳細については、PHP 中国語 Web サイトの他の関連記事を参照してください。

関連ラベル:
ソース:php.cn
このウェブサイトの声明
この記事の内容はネチズンが自主的に寄稿したものであり、著作権は原著者に帰属します。このサイトは、それに相当する法的責任を負いません。盗作または侵害の疑いのあるコンテンツを見つけた場合は、admin@php.cn までご連絡ください。
人気のチュートリアル
詳細>
最新のダウンロード
詳細>
ウェブエフェクト
公式サイト
サイト素材
フロントエンドテンプレート