>  기사  >  백엔드 개발  >  golang의 Websocket을 사용하여 실시간 지도 기능을 개발하는 방법

golang의 Websocket을 사용하여 실시간 지도 기능을 개발하는 방법

WBOY
WBOY원래의
2023-12-02 13:49:41770검색

golang의 Websocket을 사용하여 실시간 지도 기능을 개발하는 방법

Golang의 Websocket을 사용하여 실시간 지도 기능을 개발하는 방법

오늘날의 웹 애플리케이션 개발에서는 실시간 요구 사항이 점점 더 높아지고 있으며, 특히 실시간 지도 기능과 같은 지리적 위치 관련 애플리케이션과 관련된 요구 사항이 더욱 높아지고 있습니다. . Golang의 Websocket 기술은 실시간 지도 기능 개발에 적합한 빠르고 실시간 양방향 통신을 제공할 수 있습니다. 이 글에서는 Golang의 Websocket을 사용하여 실시간 지도 기능을 개발하는 방법을 소개하고 구체적인 코드 예제를 제공하겠습니다.

1. 기본 개념

1.1 Websocket

Websocket은 HTML5에서 도입된 새로운 프로토콜로, 기존 HTTP 프로토콜에 양방향 통신을 구현하는 기술입니다. Websocket은 HTTP/HTTPS의 표준 포트를 사용하여 클라이언트와 서버 사이에 긴 연결을 설정하므로 서버가 실시간으로 클라이언트에 데이터를 푸시할 수 있습니다. 동시에 Websocket은 TCP 프로토콜과 유사한 양방향 통신도 지원하므로 클라이언트와 서버가 동시에 데이터를 전송할 수 있습니다.

1.2 Golang

Golang은 빠르고 효율적이며 안전한 프로그래밍 언어로, 특히 웹 개발에 적합합니다. Golang의 Websocket 개발은 표준 net/http 라이브러리에서 제공하는 websocket 모듈을 사용할 수 있어 매우 편리하고 간단합니다.

2. 구현 단계

2.1 환경 설정

먼저 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. 실시간 지도 예시

아래에서는 위의 두 부분을 결합하고 Golang의 Websocket 기술을 사용하여 실시간 지도 기능을 구현해 보겠습니다.

3.1 백엔드 구현

서버 측에서는 Golang의 표준 라이브러리 "net/http"와 타사 라이브러리 "gorilla/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 연결을 설정한 다음 보내기 기능을 사용하여 서버에 정보를 보내고 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>

IV. 요약

본 글에서는 Golang의 Websocket 기술의 기본 개념을 소개한 후 실시간 지도 기능의 개발 예시를 제공합니다. 위의 예는 HTML5 및 SVG 태그를 통해 지도를 그리고 Websocket 기술을 사용하여 실시간 양방향 통신을 달성하고 실시간 지도 기능을 실현할 수 있습니다. 물론 위의 내용은 실제 시나리오에 불과하며 특정 애플리케이션 요구 사항에 따라 적절한 개선과 최적화가 이루어져야 합니다.

위 내용은 golang의 Websocket을 사용하여 실시간 지도 기능을 개발하는 방법의 상세 내용입니다. 자세한 내용은 PHP 중국어 웹사이트의 기타 관련 기사를 참조하세요!

성명:
본 글의 내용은 네티즌들의 자발적인 기여로 작성되었으며, 저작권은 원저작자에게 있습니다. 본 사이트는 이에 상응하는 법적 책임을 지지 않습니다. 표절이나 침해가 의심되는 콘텐츠를 발견한 경우 admin@php.cn으로 문의하세요.