Bagaimana untuk mendaftar sambungan websocket baharu dengan gooptic

WBOY
Lepaskan: 2024-02-08 22:18:20
ke hadapan
529 orang telah melayarinya

如何注册新的 websocket 连接 gooptic

editor php Yuzai akan memperkenalkan anda cara mendaftar sambungan soket web baharu dengan gooptic. GoOptic ialah perpustakaan soket web bahasa Go sumber terbuka untuk membina aplikasi komunikasi masa nyata berprestasi tinggi. Untuk mendaftarkan sambungan websoket baharu, anda perlu mengimport pustaka GoOptic dalam program Go anda terlebih dahulu. Anda kemudiannya boleh menggunakan fungsi yang disediakan oleh GoOptic untuk mencipta pelayan soket web dan menentukan alamat dan port untuk mendengar. Seterusnya, anda boleh menggunakan fungsi HandleFunc yang disediakan oleh GoOptic untuk mengendalikan pelbagai acara sambungan soket web, seperti menerima mesej, menghantar mesej, dsb. Akhir sekali, panggil fungsi Serve yang disediakan oleh GoOptic untuk memulakan pelayan soket web supaya ia boleh menerima sambungan baharu. Dengan langkah-langkah ini, anda boleh berjaya mendaftarkan sambungan soket web baharu dengan gooptic.

Kandungan soalan

Saya cuba menyediakan pelayan soket web mudah yang sepatutnya menyampaikan beberapa kandungan kepada pelanggan pada selang masa yang tidak diketahui.

Kod saya pada masa ini kelihatan seperti ini:

router.go

func setuproutes(app *fiber.app) error {

    app.get("/whop/validate", handler.handlewhopvalidate)
    /*other non-websocket routes*/

    /*...*/

    app.get("/ws/monitor", websocket.new(wshandler.handlewsmonitor))

    app.use(func(c *fiber.ctx) error {
        c.sendstatus(404)
        return c.next()
    })

    return nil
}
Salin selepas log masuk

pengendali.go

package handlers

import (
    "fmt"
    "log"

    "github.com/gofiber/websocket/v2"
)

var register = make(chan *websocket.conn)
var unregister = make(chan *websocket.conn)

func handlewsmonitor(c *websocket.conn) {
    go socketlistener()
    defer func() {
        unregister <- c
        //may need to check whether connection is already closed before re-closing?
        c.close()
    }()
    //sends conn into channel
    register <- c
    for {
        messagetype, message, err := c.readmessage()
        if err != nil {
            if websocket.isunexpectedcloseerror(err, websocket.closegoingaway, websocket.closeabnormalclosure) {
                log.println("read error:", err)
            }
            return
        }
        if messagetype == websocket.textmessage {
            log.println("got textmessage:", string(message))
        } else {
            log.println("received message of type:", messagetype)
        }
    }
}

func socketlistener() {
    for {
        select {
        case c := <-register:
            messagetype, message, err := c.readmessage()
            if err != nil {
                log.println(err)
                unregister <- c
                return
            }

            fmt.printf("got message of type: %d\nmessage:%s\n", messagetype, string(message))
            fmt.printf("connection params: %s\n", c.params("id"))
            //append to list of co
        case c := <-unregister:
            //remove conection from list of clients
            c.close()
            fmt.printf("closed connection\n")

        }

    }
}
Salin selepas log masuk

Masalah yang saya hadapi ialah apabila saya menyambung ke websocket kes pilihan pendaftaran saya hilang (saya ingin mendaftar sambungan klien ke peta menggunakan uuid yang saya berikan kepada pelanggan tadi) .

client.go

package main

import (
    "flag"
    "log"
    "net/url"

    "github.com/fasthttp/websocket"
)

type Client struct {
    C *websocket.Conn
}

func main() {
    addr := flag.String("addr", "localhost:8080", "http service address")
    u := url.URL{
        Scheme:   "ws",
        Host:     *addr,
        Path:     "/ws/monitor",
        RawQuery: "id=12",
    }
    wsClient := &Client{}

    log.Printf("connecting to %s\n", u.String())
    // Connect to the WebSocket server
    conn, resp, err := websocket.DefaultDialer.Dial(u.String(), nil)
    if err != nil {
        log.Fatal("Dial:", err)
    }
    wsClient.C = conn
    if resp != nil {
        log.Println("Got response:", resp)
    }
    defer wsClient.closeConn()
}

func (client *Client) closeConn() {
    err := client.C.WriteMessage(
        websocket.CloseMessage,
        websocket.FormatCloseMessage(websocket.CloseNormalClosure, ""),
    )
    if err != nil {
        log.Println("Write close:", err)
        return
    }
    client.C.Close()
    log.Println("Connection closed")
}
Salin selepas log masuk
Adakah terdapat sesuatu yang hilang dalam

handler.go atau patutkah saya mengambil pendekatan berbeza apabila menggunakan klien untuk menyambung ke pelayan?

Penyelesaian

Menurut ujian saya, kes pilihan daftar memang terkena (kod yang saya gunakan dilampirkan di bahagian bawah jawapan ini).

Tetapi saya menemui isu lain dalam kod:

    Kebuntuan berlaku antara
  1. unregister chan 是无缓冲的,socketlistener 中的 unregister <- c​​ 将被阻塞。当代码到达 unregister <- c​​ 时,它和 case c := <-unregister.
  2. Nampaknya kami hanya memerlukan satu socketlistener goroutine。如果是这种情况,应将其移至 handlewsmonitor untuk keseluruhan pelayan.
  3. handlewsmonitorsocketlistener 都从连接中读取。 socketlistenerApakah tanggungjawab anda? Nampaknya ia tidak sepatutnya dibaca dari sambungan.

Difikirkan semula, nampaknya ia boleh dipadam sepenuhnya terus dalam handlewsmonitor中的地图上添加连接和删除连接。 socketlistener. Kesederhanaan harus menjadi matlamat utama reka bentuk. Lihat prinsip ciuman.

package main

import (
    "log"

    "github.com/gofiber/fiber/v2"
    "github.com/gofiber/websocket/v2"
)

var (
    register   = make(chan *websocket.Conn)
    unregister = make(chan *websocket.Conn)
)

func main() {
    // Make it easy to find out which line prints the log.
    log.SetFlags(log.Lshortfile)
    app := fiber.New()

    app.Get("/ws/monitor", websocket.New(HandleWsMonitor))

    log.Fatal(app.Listen(":8080"))
}

func HandleWsMonitor(c *websocket.Conn) {
    // It seems the we only need one SocketListener goroutine for the whole server.
    // If this is the case, the next line should be moved outside of this func.
    go SocketListener()
    defer func() {
        unregister <- c
        c.Close()
    }()

    register <- c
    for {
        messageType, message, err := c.ReadMessage()
        if err != nil {
            if websocket.IsUnexpectedCloseError(err, websocket.CloseGoingAway, websocket.CloseAbnormalClosure) {
                log.Println("read error:", err)
            }
            return
        }
        if messageType == websocket.TextMessage {
            log.Println("got textmessage:", string(message))
        } else {
            log.Println("received message of type:", messageType)
        }
    }
}

func SocketListener() {
    for {
        select {
        case c := <-register:
            // This did appear in the log.
            log.Println("case c := <-register")
            messageType, message, err := c.ReadMessage()
            if err != nil {
                log.Println(err)
                // unregister is unbuffered, the sending will be blocked.
                unregister <- c
                // If we use only one SocketListener goroutine then it should
                // not return here.
                return
            }

            log.Printf("Got message of type: %d\nMessage:%s\n", messageType, string(message))
            log.Printf("Connection Params: %s\n", c.Params("id"))
        case c := <-unregister:
            c.Close()
            log.Println("Closed connection")

        }
    }
}
Salin selepas log masuk

Atas ialah kandungan terperinci Bagaimana untuk mendaftar sambungan websocket baharu dengan gooptic. Untuk maklumat lanjut, sila ikut artikel berkaitan lain di laman web China PHP!

Label berkaitan:
sumber:stackoverflow.com
Kenyataan Laman Web ini
Kandungan artikel ini disumbangkan secara sukarela oleh netizen, dan hak cipta adalah milik pengarang asal. Laman web ini tidak memikul tanggungjawab undang-undang yang sepadan. Jika anda menemui sebarang kandungan yang disyaki plagiarisme atau pelanggaran, sila hubungi admin@php.cn
Tutorial Popular
Lagi>
Muat turun terkini
Lagi>
kesan web
Kod sumber laman web
Bahan laman web
Templat hujung hadapan
Tentang kita Penafian Sitemap
Laman web PHP Cina:Latihan PHP dalam talian kebajikan awam,Bantu pelajar PHP berkembang dengan cepat!