php小编鱼仔为您介绍如何注册新的websocket连接gooptic。GoOptic是一个开源的Go语言websocket库,用于构建高性能、实时通信的应用程序。要注册新的websocket连接,首先需要在Go程序中导入GoOptic库。然后,可以使用GoOptic提供的函数来创建websocket服务器,并指定要监听的地址和端口。接下来,可以使用GoOptic提供的HandleFunc函数来处理websocket连接的各种事件,例如接收消息、发送消息等。最后,调用GoOptic提供的Serve函数来启动websocket服务器,使其可以接受新的连接。通过这些步骤,您就可以成功注册新的websocket连接gooptic。
问题内容
我正在尝试设置一个简单的 websocket 服务器,该服务器应该以未知的时间间隔为客户端提供一些内容。
我的代码目前如下所示:
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 }
handler.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") } } }
我遇到的问题是,当我连接到 websocket 时,我的注册选择案例未命中(我想使用之前提供给客户端的 uuid 将客户端连接注册到地图) .
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") }
handler.go 中是否缺少某些内容,或者我在使用客户端连接到服务器时是否应该采取不同的方法?
解决方法
根据我的测试,寄存器的选择案例确实命中(我使用的代码附在这个答案的底部)。
但是我在代码中发现了其他问题:
-
unregister
chan 是无缓冲的,socketlistener
中的unregister 将被阻塞。当代码到达 <code>unregister 时,它和 <code>case c := 之间出现死锁。
- 看来我们整个服务器只需要一个
socketlistener
goroutine。如果是这种情况,应将其移至handlewsmonitor
之外。 -
handlewsmonitor
和socketlistener
都从连接中读取。socketlistener
的职责是什么?看来它不应该从连接中读取。
再想一想,好像可以直接在handlewsmonitor
中的地图上添加连接和删除连接。 socketlistener
可以完全删除。简单性应该是设计的一个关键目标。请参阅kiss 原则。
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") } } }
以上是如何注册新的 websocket 连接 gooptic的详细内容。更多信息请关注PHP中文网其他相关文章!

Go语言的核心特性包括垃圾回收、静态链接和并发支持。1.Go语言的并发模型通过goroutine和channel实现高效并发编程。2.接口和多态性通过实现接口方法,使得不同类型可以统一处理。3.基本用法展示了函数定义和调用的高效性。4.高级用法中,切片提供了动态调整大小的强大功能。5.常见错误如竞态条件可以通过gotest-race检测并解决。6.性能优化通过sync.Pool重用对象,减少垃圾回收压力。

Go语言在构建高效且可扩展的系统中表现出色,其优势包括:1.高性能:编译成机器码,运行速度快;2.并发编程:通过goroutines和channels简化多任务处理;3.简洁性:语法简洁,降低学习和维护成本;4.跨平台:支持跨平台编译,方便部署。

关于SQL查询结果排序的疑惑学习SQL的过程中,常常会遇到一些令人困惑的问题。最近,笔者在阅读《MICK-SQL基础�...

golang ...

Go语言中如何对比并处理三个结构体在Go语言编程中,有时需要对比两个结构体的差异,并将这些差异应用到第�...

GoLand中自定义结构体标签不显示怎么办?在使用GoLand进行Go语言开发时,很多开发者会遇到自定义结构体标签在�...


热AI工具

Undresser.AI Undress
人工智能驱动的应用程序,用于创建逼真的裸体照片

AI Clothes Remover
用于从照片中去除衣服的在线人工智能工具。

Undress AI Tool
免费脱衣服图片

Clothoff.io
AI脱衣机

AI Hentai Generator
免费生成ai无尽的。

热门文章

热工具

PhpStorm Mac 版本
最新(2018.2.1 )专业的PHP集成开发工具

Dreamweaver Mac版
视觉化网页开发工具

禅工作室 13.0.1
功能强大的PHP集成开发环境

螳螂BT
Mantis是一个易于部署的基于Web的缺陷跟踪工具,用于帮助产品缺陷跟踪。它需要PHP、MySQL和一个Web服务器。请查看我们的演示和托管服务。

SublimeText3汉化版
中文版,非常好用