当前位置: 首页 > Web前端 > HTML5

【GoWebSocket】多房间聊天室(三)自动清空无人房间

时间:2023-04-06 00:13:42 HTML5

我是公众号线下派对游戏作者HullQin(欢迎关注公众号,发加微信,交朋友),转发本文需获得作者胡琴授权。我独立开发了《联机桌游合集》,这是一个网页,在这里你可以轻松地和朋友一起玩网络游戏,五子棋等游戏,不收费,也没有广告。还为GameJam2022开发了《Dice Crush》,喜欢的话可以关注我HullQin哦~有空我会分享制作游戏的相关技术。背景《Go WebSocket》专栏,有前几篇文章:第一篇:《为什么我选用Go重构Python版本的WebSocket服务?》,介绍我的目标。第二篇文章:《你的第一个Go WebSocket服务: echo server》,介绍了如何编写WebSocket服务端。第三篇:《单房间的聊天室》,介绍如何实现单间聊天室。第四篇:《多房间的聊天室(一)思考篇》,介绍实现多房间聊天室的思路。第五篇:《多房间的聊天室(二)代码实现》,介绍实现多房间聊天室的代码。如果你还没有读过上面的文章,你必须先阅读它,因为这篇文章比较复杂。如果以上文章看不懂,这篇文章可能跟不上节奏。在上一篇文章中,我们提到房间的数量只会不断增加,房子的地图会越来越大,最终会导致内存不足。这不是一件好事。所以我们后面需要加一个优化:当最后一个客户端断开连接时,回收(删除)这个房间。今天,我们让它成为现实。思路中有一个重要的问题需要考虑清楚:这个【回收】操作是在哪里进行的?哪个协程?什么时候?如果有多个位置,是否存在竞争?回头看之前画的图:可以发现每个client连接都会有2个goroutines:Read和Write。其中,Read的重要职责是unregister,这一点我之前在《单房间的聊天室》中强调过。注销是从集线器中删除客户端连接。这个时候我们可以查看hub中是否还有其他的client,如果没有就删除。注意unregister只是一个通道,真正的处理逻辑是用goroutine写的。哪个gotoutine负责接收unregister并执行逻辑?它是集线器。所以我们需要修改Hub代码。直接看多房间聊天室案例代码的源码地址:github.com/HullQin/go-websocket-examples在chat-multi-rooms文件夹下,文章可以配合commit记录阅读:deleteemptyroom是清理未被占用房间的逻辑。开始开发。我们会根据《多房间的聊天室(二)代码实现》的代码进行修改。关注hubgoroutine的代码:func(h*Hub)run(){for{select{caseclient:=<-h.register:h.clients[client]=truecaseclient:=<-h.unregister:如果_,好的:=h.clients[client];ok{delete(h.clients,client)close(client.send)}casemessage:=<-h.broadcast:forclient:=rangeh.clients{选择{caseclient.send<-message:default:close(client.send)delete(h.clients,client)}}}}}可以看caseclient:=<-h.unregister:这段代码是处理注销逻辑的。此处删除hub中对应的client。删除时,我们只是检查h.clients是否为空。如果为空,则将hub从house(房间集合)中删除,然后结束hubgoroutine。但是,有一个问题。如果我们想在房子里删除它,这里我们需要知道密钥。关键是roomId。最好从集线器的属性中获取它。目前还不支持,所以我们需要在hub中添加一个roomId属性以方便使用。做删除。iflen(h.clients)==0{delete(house,h.roomId)break}接下来,我们添加roomId属性:typeHubstruct{//房间标识。roomIdstring//注册客户。clientsmap[*Client]bool//来自客户端的入站消息。broadcastchan[]byte//注册来自客户端的请求。registerchan*Client//注销来自客户端的请求。注销chan*Client}funcnewHub(roomIdstring)*Hub{return&Hub{roomId:roomId,broadcast:make(chan[]byte),register:make(chan*Client),unregister:make(chan*Client),clients:make(map[*Client]bool),}}另外,你需要修改main.go。创建新的hub时,传入roomId:测试一下,就大功告成了!(可以在删除逻辑中添加日志输出)现在断开连接时,未占用的房间会自动清空!并且下次进入时,也会新建一个房间,不会影响正常使用!真的可以吗?我又画了一张图(以房间为例),比较完整:我用connection表示goroutine的启动关系:当User连接到WebSocket服务器时,会先启动serveWsgoroutine。在serveWsgoroutine中,会进行register操作,这个在上图中没有画出来。然后serveWsgoroutine启动Readgoroutine和Writegoroutine,然后自己结束。这真的是不会出错的完美解决方案吗?留个悬念,我们下一篇继续讲解。最后,我是公众号线下派对游戏的作者HullQin(欢迎关注公众号,发送加微信,交友),转载本文需作者HullQin授权。我独立开发了《联机桌游合集》,这是一个网页,在这里你可以轻松地和朋友一起玩网络游戏,五子棋等游戏,不收费,也没有广告。还为GameJam2022开发了《Dice Crush》,喜欢的话可以关注我HullQin哦~有空我会分享制作游戏的相关技术。