Rumah >pembangunan bahagian belakang >Golang >Bagaimana untuk mendaftar sambungan websocket baharu dengan 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.
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 }
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") } } }
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") }Adakah terdapat sesuatu yang hilang dalam
handler.go atau patutkah saya mengambil pendekatan berbeza apabila menggunakan klien untuk menyambung ke pelayan?
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:
unregister
chan 是无缓冲的,socketlistener
中的 unregister <- c
将被阻塞。当代码到达 unregister <- c
时,它和 case c := <-unregister
. socketlistener
goroutine。如果是这种情况,应将其移至 handlewsmonitor
untuk keseluruhan pelayan. handlewsmonitor
和 socketlistener
都从连接中读取。 socketlistener
Apakah 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") } } }
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!