首頁  >  文章  >  後端開發  >  Go WebSocket 如何處理並發連線?

Go WebSocket 如何處理並發連線?

PHPz
PHPz原創
2024-06-04 09:02:00938瀏覽

Go WebSocket 處理並發連線的方法:為每個連線使用一個 Goroutine。透過 Channel 進行連線通訊。使用第三方函式庫(如 [gowebsocket](https://github.com/gobwas/ws)、[gorilla/websocket](https://github.com/gorilla/websocket))來簡化處理。

Go WebSocket 如何处理并发连接?

Go WebSocket 如何處理並發連接

WebSocket 是一種全雙工通訊協議,允許客戶端和伺服器進行即時雙向通訊。 Go 語言中處理 WebSocket 並發連線的常用方法如下:

1. Goroutine

一個簡單的解決方案是為每個連線使用一個 Goroutine。 Goroutine 是 Go 中的一種輕量級線程,可以並行執行。當一個新的WebSocket 連線建立時,我們可以建立一個新的Goroutine 來處理它:

package main

import (
    "fmt"
    "net/http"
    "os"

    "github.com/gorilla/websocket"
)

var upgrader = websocket.Upgrader{}

func main() {
    // WebSocket 服务器端口号
    port := os.Getenv("PORT")
    if port == "" {
        port = "8080"
    }

    http.HandleFunc("/", func(w http.ResponseWriter, r *http.Request) {
        // 对请求进行 WebSocket 升级
        conn, err := upgrader.Upgrade(w, r, nil)
        if err != nil {
            fmt.Println(err)
            return
        }

        // 创建一个 Goroutine 处理连接
        go handleConnection(conn)
    })

    http.ListenAndServe(":"+port, nil)
}

// handleConnection 处理一个 WebSocket 连接
func handleConnection(conn *websocket.Conn) {
    for {
        msgType, msg, err := conn.ReadMessage()
        if err != nil {
            fmt.Println(err)
            break
        }

        if msgType == websocket.TextMessage {
            // 处理文本消息
            fmt.Println("Received text message:", string(msg))
            if err := conn.WriteMessage(msgType, msg); err != nil {
                fmt.Println(err)
            }
        } else {
            // 处理其他类型的消息
        }
    }

    conn.Close()
}

2. Channel

Channel 是Go 中用於通訊的並發通道。我們可以透過一個 Channel 來處理多個連接:

package main

import (
    "fmt"
    "net/http"
    "os"
    "sync"
    "time"

    "github.com/gorilla/websocket"
)

var (
    upgrader = websocket.Upgrader{}
    connections = make(chan *websocket.Conn, 100)
    wg sync.WaitGroup
)

func main() {
    // WebSocket 服务器端口号
    port := os.Getenv("PORT")
    if port == "" {
        port = "8080"
    }

    http.HandleFunc("/", func(w http.ResponseWriter, r *http.Request) {
        // 对请求进行 WebSocket 升级
        conn, err := upgrader.Upgrade(w, r, nil)
        if err != nil {
            fmt.Println(err)
            return
        }

        // 将连接添加到 Channel
        connections <- conn
    })

    // 启动一个 Goroutine 处理 Channel 中的连接
    go handleConnections()

    http.ListenAndServe(":"+port, nil)
}

// handleConnections 处理 Channel 中的 WebSocket 连接
func handleConnections() {
    for {
        conn := <-connections

        wg.Add(1)
        go func() {
            defer wg.Done()
            for {
                msgType, msg, err := conn.ReadMessage()
                if err != nil {
                    fmt.Println(err)
                    break
                }

                if msgType == websocket.TextMessage {
                    // 处理文本消息
                    fmt.Println("Received text message:", string(msg))

                    // 向所有连接的客户端广播消息
                    for c := range connections {
                        if c != conn {
                            if err := c.WriteMessage(msgType, msg); err != nil {
                                fmt.Println(err)
                            }
                        }
                    }
                } else {
                    // 处理其他类型的消息
                }
            }

            conn.Close()
        }()
    }
}

透過管道傳遞連接可以在所有 Goroutine 之間共享連接,並避免創建過多線程帶來的開銷。

3. 第三方函式庫

還有許多第三方函式庫可以簡化WebSocket 並發處理,例如:

  • [gowebsocket]( https://github.com/gobwas/ws)
  • [gorilla/websocket](https://github.com/gorilla/websocket)
  • [fasthttp/websocket](https: //github.com/valyala/fasthttp/blob/master/websocket/websocket.go)

這些函式庫提供了高層次的API 來處理並發連接,並簡化了WebSocket 的使用。

以上是Go WebSocket 如何處理並發連線?的詳細內容。更多資訊請關注PHP中文網其他相關文章!

陳述:
本文內容由網友自願投稿,版權歸原作者所有。本站不承擔相應的法律責任。如發現涉嫌抄襲或侵權的內容,請聯絡admin@php.cn