>  기사  >  백엔드 개발  >  Go 언어를 사용하여 멀티스레드 웹소켓 통신을 구현하는 방법

Go 언어를 사용하여 멀티스레드 웹소켓 통신을 구현하는 방법

WBOY
WBOY원래의
2023-12-14 13:45:441106검색

Go 언어를 사용하여 멀티스레드 웹소켓 통신을 구현하는 방법

최근에는 실시간 소통이 기본이 되었습니다. WebSocket은 클라이언트와 서버 간의 실시간 통신을 보다 빠르고 효과적으로 구현할 수 있는 실시간 통신의 선두주자입니다. Go 언어도 최근 몇 년 동안 인기 있는 언어였으며 실시간 통신에 널리 사용되었습니다. Go 언어의 장점과 멀티스레드 처리의 특성을 활용하여 Websocket의 통신 기능을 보다 효율적이고 안정적으로 구현할 수 있습니다.

이 기사에서는 Go 언어에 중점을 두고 이를 사용하여 몇 가지 중요한 기능 구현을 포함하여 다중 스레드 웹소켓 통신을 구현하는 방법을 소개하고 자세한 코드 예제를 제공합니다.

Websocket 구현

Go 언어를 사용하여 Websocket 통신을 구현하기 전에 Websocket 통신에 대한 기본 지식을 이해해야 합니다. Websocket은 HTTP와 마찬가지로 TCP 기반의 네트워크 프로토콜입니다. 그러나 차이점은 요청 및 응답 모드가 아니라 클라이언트와 서버 간의 지속적인 연결로 두 당사자 간의 실시간 통신이 가능하다는 점입니다.

Go 언어에서 Websocket 통신을 구현하는 첫 번째 단계는 "net/http" 및 "github.com/gorilla/websocket" 패키지를 가져오는 것입니다. 그 중 "net/http"는 HTTP 서버를 생성하는 데 사용되며 "github.com/gorilla/websocket"은 Websocket용 타사 패키지입니다. 이 패키지를 사용할 수 없는 경우 "go get" 명령을 사용하여 설치할 수 있습니다.

import (
    "fmt"
    "net/http"
    "github.com/gorilla/websocket"
)

Websocket 연결 생성

다음과 같이 "http.HandleFunc()" 메서드를 사용하여 Go 언어에서 Websocket 연결을 설정합니다.

func main() {
    http.HandleFunc("/", handleConnections)

    http.ListenAndServe(":4000", nil)
}

위 코드는 "http.HandleFunc()" 메서드를 사용하여 생성합니다. Websocket 연결 설정을 담당하는 "handleConnections" 처리 기능이라는 연결입니다. 보시다시피 Websocket 연결을 위한 요청 경로는 루트 디렉터리인 "/"입니다.

연결 요청 처리

Websocket 연결을 설정한 후 프로토콜 업그레이드, 읽기 및 쓰기 캐시 크기, 하트비트 시간 제한 등과 같은 연결 요청에 대한 몇 가지 기본 매개변수를 구성해야 합니다.

var upgrader = websocket.Upgrader{
    ReadBufferSize: 1024,
    WriteBufferSize: 1024,
    CheckOrigin: func(r *http.Request) bool {
        return true
    },
}

위 코드는 "websocket.Upgrader"를 사용하여 구성됩니다. 여기서 "ReadBufferSize" 및 "WriteBufferSize"는 읽기 및 쓰기 버퍼의 크기를 지정하고 "CheckOrigin"은 "true"로 설정되어 모든 소스 액세스 요청을 나타냅니다. 허용됩니다. 특정 소스가 필요한 경우 특정 요구 사항에 따라 설정할 수 있습니다.

연결 요청 처리

웹소켓 연결 요청이 처리된 후 프로토콜 업그레이드를 위해서는 표준 웹소켓 프로토콜 핸드셰이크를 따라야 합니다. Go 언어에서 프로토콜 업그레이드는 업그레이드를 사용하여 프로토콜 핸드셰이크를 수행하고 연결 핸들(conn)을 반환할 수 있습니다. 연결 핸들은 Websocket 연결 수명 주기 동안 메시지를 보내고 받는 데 사용할 수 있습니다.

func handleConnections(w http.ResponseWriter, r *http.Request) {
    // 通过Upgrader进行协议升级
    ws, err := upgrader.Upgrade(w, r, nil)
    if err != nil {
        fmt.Println(err)
    }

    // 若协议升级成功,则跳转到另一个处理函数处理消息
    go handleMessages(ws)
}

handleConnections 함수에서는 먼저 Upgrader를 통해 프로토콜이 업그레이드됩니다. 업그레이드가 성공하면 "go handlerMessages(ws)"를 호출하여 고루틴을 시작하여 Websocket 메시지 처리를 시작합니다.

Websocket 메시지 처리

다음 단계는 Websocket 메시지를 처리하는 것입니다. Go 언어에서는 무한 루프를 사용하여 Websocket 메시지 도착을 모니터링한 다음 그에 따라 각 메시지를 처리할 수 있습니다.

func handleMessages(ws *websocket.Conn) {
    for {
        messageType, p, err := ws.ReadMessage()
        if err != nil {
            fmt.Println(err)
            return
        }

        // 根据消息类型进行处理
        switch messageType {
        case websocket.TextMessage:
            // 处理text类型消息
            fmt.Println(string(p))
        case websocket.BinaryMessage:
            // 处理binary类型消息
            fmt.Println(p)
        }
    }
}

handMessages 함수에서 먼저 "ws.ReadMessage()" 메서드를 사용하여 Websocket 메시지를 읽고 메시지 유형에 따라 처리합니다.

Send Websocket message

마지막 부분은 Websocket 메시지를 보내는 부분입니다. Go 언어에서는 Websocket 연결 핸들 "ws"를 사용하여 클라이언트에 데이터를 보낼 수 있습니다.

func sendMessage(ws *websocket.Conn, messageType int, message []byte) error {
    if err := ws.WriteMessage(messageType, message); err != nil {
        return err
    }

    return nil
}

sendMessage 함수에서는 먼저 "ws.WriteMessage()" 메소드를 통해 클라이언트에게 메시지를 보냅니다.

멀티 스레드 웹소켓 처리

웹소켓 통신의 효율성을 높이기 위해서는 웹소켓 메시지 처리에 멀티스레딩을 사용해야 합니다. Go 언어에서는 goroutine을 사용하여 동시 처리를 구현할 수 있습니다.

고루틴 시작

Go 언어에서 고루틴을 시작하는 것은 매우 간단합니다. 함수 앞에 "go"를 추가하기만 하면 됩니다.

go handleMessages(ws)

브로드캐스트 메시지

실제 개발에서 Websocket은 일반적으로 브로드캐스트 메시지를 구현해야 합니다. 즉, 연결된 모든 클라이언트에 메시지를 보냅니다. Go 언어에서는 맵을 사용하여 연결된 모든 클라이언트를 저장한 다음 순회하여 각 클라이언트에 메시지를 차례로 보낼 수 있습니다.

var clients = make(map[*websocket.Conn]bool) // 所有连接的客户端
var broadcast = make(chan []byte) // 广播通道

func main() {
    http.HandleFunc("/", handleConnections)
    go handleMessages()

    http.ListenAndServe(":4000", nil)
}

func handleConnections(w http.ResponseWriter, r *http.Request) {
    // 通过Upgrader进行协议升级
    ws, err := upgrader.Upgrade(w, r, nil)
    if err != nil {
        fmt.Println(err)
    }

    // 若协议升级成功,则将客户端存入map
    clients[ws] = true
}

func handleMessages() {
    for {
        // 从广播通道中获取消息
        message := <- broadcast
        // 对所有连接的客户端发送消息
        for client := range clients {
            if err := client.WriteMessage(websocket.TextMessage, message); err != nil {
                fmt.Println(err)
                delete(clients, client)
                return
            }
        }
    }
}

위 코드에서는 방송 메시지를 처리하기 위해 방송 채널(broadcast)을 구현했습니다. 동시에 연결된 모든 클라이언트를 저장하기 위한 맵(클라이언트)이 생성됩니다. handlerConnections 함수에서 새 클라이언트가 연결되면 클라이언트에 저장됩니다. HandleMessages 함수에서 브로드캐스트 채널은 새 메시지를 가져와 연결된 모든 클라이언트에 보냅니다.

동시성 안전성 보장

멀티스레딩이 웹소켓 메시지를 처리하는 동안 데이터 동시성 안전성을 보장하는 것이 필요합니다. Go 언어에서는 동시성 보안 제어를 위해 잠금을 사용할 수 있습니다. 이 기사의 샘플 코드에서 "sync.RWMutex"는 동시성 안전을 보장하기 위해 읽기-쓰기 잠금을 구현하는 데 사용됩니다.

var mutex = &sync.RWMutex{}

func handleConnections(w http.ResponseWriter, r *http.Request) {
    // 通过Upgrader进行协议升级
    ws, err := upgrader.Upgrade(w, r, nil)
    if err != nil {
        fmt.Println(err)
    }

    // 若协议升级成功,则将客户端存入map,并进行锁定
    mutex.Lock()
    clients[ws] = true
    mutex.Unlock()
}

func handleMessages() {
    for {
        // 从广播通道中获取消息,并加锁
        message := <- broadcast
        mutex.Lock()
        for client := range clients {
            if err := client.WriteMessage(websocket.TextMessage, message); err != nil {
                fmt.Println(err)
                client.Close()
                delete(clients, client)
            }
        }
        mutex.Unlock()
    }
}

handleConnections 함수에서 연결이 성공한 후 클라이언트가 맵에 추가되고 잠깁니다. 데이터 보안을 보장하기 위해 handlerMessages 함수에서 새 메시지를 처리하기 전에 이를 잠급니다.

요약하자면, Go 언어를 사용하여 멀티스레드 웹소켓 통신을 구현하면 웹소켓 통신의 효율성과 안정성을 향상시킬 수 있으며 브로드캐스트 메시지를 쉽게 구현할 수 있습니다. 실제로는 특정 요구에 따라 더 복잡한 기능을 구현할 수 있습니다.

위 내용은 Go 언어를 사용하여 멀티스레드 웹소켓 통신을 구현하는 방법의 상세 내용입니다. 자세한 내용은 PHP 중국어 웹사이트의 기타 관련 기사를 참조하세요!

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