Heim  >  Artikel  >  Backend-Entwicklung  >  So verwenden Sie Golangs Websocket, um Echtzeit-Kartenfunktionen zu entwickeln

So verwenden Sie Golangs Websocket, um Echtzeit-Kartenfunktionen zu entwickeln

WBOY
WBOYOriginal
2023-12-02 13:49:41721Durchsuche

So verwenden Sie Golangs Websocket, um Echtzeit-Kartenfunktionen zu entwickeln

So verwenden Sie Golangs Websocket zur Entwicklung von Echtzeit-Kartenfunktionen

In der heutigen Entwicklung von Webanwendungen werden die Echtzeitanforderungen immer höher, insbesondere bei Anwendungen, die sich auf den geografischen Standort beziehen, wie z. B. Echtzeit-Kartenfunktionen . Die Websocket-Technologie von Golang kann eine schnelle und bidirektionale Echtzeitkommunikation ermöglichen, die für die Entwicklung von Echtzeit-Kartenfunktionen geeignet ist. In diesem Artikel werde ich Ihnen vorstellen, wie Sie Golangs Websocket verwenden, um Echtzeit-Kartenfunktionen zu entwickeln, und gleichzeitig spezifische Codebeispiele bereitstellen.

1. Grundkonzepte

1.1 Websocket

Websocket ist ein neues Protokoll, das von HTML5 eingeführt wurde. Es handelt sich um eine Technologie, die eine bidirektionale Kommunikation auf dem traditionellen HTTP-Protokoll herstellt. Websocket verwendet den Standardport von HTTP/HTTPS, um eine lange Verbindung zwischen dem Client und dem Server herzustellen, sodass der Server Daten in Echtzeit an den Client übertragen kann. Gleichzeitig unterstützt Websocket auch eine bidirektionale Kommunikation ähnlich dem TCP-Protokoll, sodass Client und Server gleichzeitig Daten übertragen können.

1.2 Golang

Golang ist eine schnelle, effiziente und sichere Programmiersprache, die sich besonders für die Webentwicklung eignet. Die Websocket-Entwicklung von Golang kann das von der Standard-Net/http-Bibliothek bereitgestellte Websocket-Modul verwenden, was sehr praktisch und einfach ist.

2. Implementierungsschritte

2.1 Umgebungseinrichtung

Zuerst müssen Sie Golang installieren, das von der offiziellen Website heruntergeladen und installiert werden kann. Geben Sie dann den folgenden Befehl in die Befehlszeile ein, um das Websocket-Modul zu installieren:

go get github.com/gorilla/websocket

2.2 Backend-Implementierung

In Golang ist das Schreiben eines Websocket-Servers relativ einfach. Mit der HandleFunc-Funktion der http-Bibliothek können Sie einen Router erstellen und die Anforderungsverarbeitungsfunktion angeben. Verwenden Sie in der Verarbeitungsfunktion die Upgrader-Funktion der Websocket-Bibliothek, um das HTTP-Protokoll auf das Websocket-Protokoll umzustellen, und verwenden Sie die Funktionen ReadMessage und WriteMessage, um eine bidirektionale Kommunikation zu erreichen. Das Folgende ist ein einfaches Beispiel:

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 Front-End-Implementierung

Verwenden Sie im Front-End JavaScript, um eine Websocket-Verbindung herzustellen, verwenden Sie dann die Sendefunktion, um Informationen an den Server zu senden, und verwenden Sie die Onmessage-Funktion zum Empfangen Vom Server gepushte Nachrichten. Das Folgende ist ein einfaches Beispiel:

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. Beispiel für eine Echtzeitkarte

Im Folgenden kombinieren wir die beiden oben genannten Teile und verwenden die Websocket-Technologie von Golang, um eine Echtzeitkartenfunktion zu implementieren.

3.1 Backend-Implementierung

Auf der Serverseite können wir Golangs Standardbibliothek „net/http“ und die Drittanbieterbibliothek „gorilla/websocket“ verwenden, um die Websocket-Kommunikation zu implementieren. Der spezifische Code lautet wie folgt:

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 Front-End-Implementierung

Verwenden Sie im Front-End JavaScript, um eine Websocket-Verbindung herzustellen, verwenden Sie dann die Sendefunktion, um Informationen an den Server zu senden, und verwenden Sie die Onmessage-Funktion zum Empfangen Vom Server gepushte Nachrichten. HTML5-Live-Karten können mithilfe von SVG-Tags gezeichnet werden. Das Folgende ist ein einfaches Beispiel:

<!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>

IV. Zusammenfassung

Nachdem die Grundkonzepte der Websocket-Technologie von Golang vorgestellt wurden, bietet dieser Artikel ein Entwicklungsbeispiel für die Echtzeit-Kartenfunktion. Das obige Beispiel kann eine Karte über HTML5- und SVG-Tags zeichnen, die Websocket-Technologie verwenden, um eine bidirektionale Kommunikation in Echtzeit zu erreichen, und die Echtzeit-Kartenfunktion realisieren. Natürlich sind die oben genannten Beispiele nur Beispiele. In tatsächlichen Szenarien müssen entsprechende Verbesserungen und Optimierungen entsprechend den spezifischen Anwendungsanforderungen vorgenommen werden.

Das obige ist der detaillierte Inhalt vonSo verwenden Sie Golangs Websocket, um Echtzeit-Kartenfunktionen zu entwickeln. Für weitere Informationen folgen Sie bitte anderen verwandten Artikeln auf der PHP chinesischen Website!

Stellungnahme:
Der Inhalt dieses Artikels wird freiwillig von Internetnutzern beigesteuert und das Urheberrecht liegt beim ursprünglichen Autor. Diese Website übernimmt keine entsprechende rechtliche Verantwortung. Wenn Sie Inhalte finden, bei denen der Verdacht eines Plagiats oder einer Rechtsverletzung besteht, wenden Sie sich bitte an admin@php.cn