>  기사  >  백엔드 개발  >  Go WebSocket은 동시 연결을 어떻게 처리합니까?

Go WebSocket은 동시 연결을 어떻게 처리합니까?

PHPz
PHPz원래의
2024-06-04 09:02:00974검색

동시 연결을 처리하기 위한 Go WebSocket의 접근 방식: 각 연결에 대해 Goroutine을 사용합니다. 채널을 통해 통신을 연결합니다. [gowebsocket](https://github.com/gobwas/ws), [gorilla/websocket](https://github.com/gorilla/websocket)과 같은 타사 라이브러리를 사용하여 처리를 단순화하세요.

Go WebSocket 如何处理并发连接?

Go WebSocket이 동시 연결을 처리하는 방법

WebSocket은 클라이언트와 서버 간의 실시간 양방향 통신을 허용하는 전이중 통신 프로토콜입니다. Go에서 WebSocket 동시 연결을 처리하는 일반적인 방법은 다음과 같습니다.

1. Goroutine

간단한 해결책은 각 연결에 Goroutine을 사용하는 것입니다. 고루틴은 병렬로 실행될 수 있는 Go의 경량 스레드입니다. 새로운 WebSocket 연결이 설정되면 이를 처리하기 위한 새로운 고루틴을 생성할 수 있습니다:

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은 Go에서 통신에 사용되는 동시 채널입니다. 채널을 통해 여러 연결을 처리할 수 있습니다:

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()
        }()
    }
}

파이프를 통해 연결을 전달하면 모든 고루틴 간에 연결을 공유할 수 있고 너무 많은 스레드를 생성하는 오버헤드를 피할 수 있습니다.

3. 타사 라이브러리

다음과 같이 WebSocket 동시 처리를 단순화할 수 있는 타사 라이브러리가 많이 있습니다.

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

이 라이브러리는 동시 연결을 처리하고 WebSocket 사용을 단순화하는 고급 API를 제공합니다.

위 내용은 Go WebSocket은 동시 연결을 어떻게 처리합니까?의 상세 내용입니다. 자세한 내용은 PHP 중국어 웹사이트의 기타 관련 기사를 참조하세요!

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