gin框架实现websocket并广播消息

2023-02-01 23:08 go 880 0
一、项目预览二、安装gin框架gogetgithub.com/gin-gonic/gin三、安装gorilla/websocket库gogetgithub.com/gorilla/websocket四、服务端实现新建main.go文件1.简单版本packagemainimport("encoding/json""net/http""github.com/gin-gonic/gin""github.com/gorilla/websocket")//连接成功结构体typeconnectedDataSstruct{Eventstring`json:"_event"`HistoryClientNumint`json:"historyClientNum"`OnlineClientNumint`json:"onlineClientNum"`}//消息结构体typemessageDataSstruct{Eventstring`json:"_event"`Messagestring`json:"message"`}//wsupGradervarupGrader=websocket.Upgrader{CheckOrigin:func(r*http.Request)bool{returntrue},}//全部客户端varclients=make(map[*websocket.Conn]bool)//存储数据var(historyClientNum=0)//广播消息funcbroadcastMsg(mtint,message[]byte){forclient:=rangeclients{client.WriteMessage(mt,message)}}//存储当前客户端funcsaveClient(client*websocket.Conn){clients[client]=true//更新历史客户端数historyClientNum++//广播进入vardata=connectedDataS{Event:"connected",HistoryClientNum:historyClientNum,OnlineClientNum:len(clients),}vardataJson,_=json.Marshal(data)broadcastMsg(websocket.TextMessage,dataJson)}//删除当前客户端funcdelClient(client*websocket.Conn){//断开连接删除clientdelete(clients,client)//广播离开vardata=connectedDataS{Event:"connected",HistoryClientNum:historyClientNum,OnlineClientNum:len(clients),}vardataJson,_=json.Marshal(data)broadcastMsg(websocket.TextMessage,dataJson)}//发送消息funcsendMsg(mtint,message[]byte){vardata=messageDataS{Event:"message",Message:string(message),}dataJson,_:=json.Marshal(data)broadcastMsg(mt,dataJson)}//创建客户端实例funccreateWs(c*gin.Context){//创建ws连接客户端client,err:=upGrader.Upgrade(c.Writer,c.Request,nil)iferr!=nil{return}//连接成功后存储当前客户端saveClient(client)deferfunc(){client.Close()delClient(client)}()for{//监听接受信息mt,message,err:=client.ReadMessage()iferr==nil{sendMsg(mt,message)}else{break}}}funcmain(){router:=gin.Default()router.LoadHTMLFiles("index.html")router.GET("/",func(c*gin.Context){c.HTML(http.StatusOK,"index.html",nil)})router.GET("/ws",createWs)router.Run(":9999")}2.正常版本packagemainimport("encoding/json""log""net/http""github.com/gin-gonic/gin""github.com/gorilla/websocket")//连接成功结构体typeconnectedDataSstruct{Eventstring`json:"_event"`HistoryClientNumint`json:"historyClientNum"`OnlineClientNumint`json:"onlineClientNum"`}//消息结构体typemessageDataSstruct{Eventstring`json:"_event"`Messagestring`json:"message"`}//存储数据var(historyClientNum=0)//广播消息funcbroadcastMsg(hub*Hub,mtint,message[]byte){forclient:=rangehub.clients{client.conn.WriteMessage(mt,message)}}//客户端实例typeClientstruct{hub*Hubconn*websocket.Connsendchan[]byte}//读取数据通道func(c*Client)readPump(){deferfunc(){c.hub.unregister<-cc.conn.Close()}()for{_,message,err:=c.conn.ReadMessage()iferr==nil{c.hub.broadcast<-message}else{break}}}//发送数据通道func(c*Client)writePump(){deferfunc(){c.conn.Close()}()formessage:=rangec.send{vardata=messageDataS{Event:"message",Message:string(message),}dataJson,_:=json.Marshal(data)c.conn.WriteMessage(websocket.TextMessage,dataJson)}}//wshubtypeHubstruct{clientsmap[*Client]boolbroadcastchan[]byteregisterchan*Clientunregisterchan*Client}//运行hubfunc(h*Hub)run(){for{select{caseclient:=<-h.register:h.clients[client]=true//更新历史客户端数historyClientNum++//广播进入vardata=connectedDataS{Event:"connected",HistoryClientNum:historyClientNum,OnlineClientNum:len(h.clients),}vardataJson,_=json.Marshal(data)broadcastMsg(h,websocket.TextMessage,dataJson)caseclient:=<-h.unregister:if_,ok:=h.clients[client];ok{delete(h.clients,client)close(client.send)//广播离开vardata=connectedDataS{Event:"connected",HistoryClientNum:historyClientNum,OnlineClientNum:len(h.clients),}vardataJson,_=json.Marshal(data)broadcastMsg(h,websocket.TextMessage,dataJson)}casemessage:=<-h.broadcast:forclient:=rangeh.clients{select{caseclient.send<-message:default:close(client.send)delete(h.clients,client)}}}}}//链接实例funcnewHub()*Hub{return&Hub{broadcast:make(chan[]byte),register:make(chan*Client),unregister:make(chan*Client),clients:make(map[*Client]bool),}}//wsupGradervarupGrader=websocket.Upgrader{CheckOrigin:func(r*http.Request)bool{returntrue},}funccreateWs(c*gin.Context,hub*Hub){conn,err:=upGrader.Upgrade(c.Writer,c.Request,nil)iferr!=nil{log.Println(err)return}client:=&Client{hub:hub,conn:conn,send:make(chan[]byte,256)}goclient.writePump()goclient.readPump()client.hub.register<-client}funcmain(){hub:=newHub()gohub.run()router:=gin.Default()router.LoadHTMLFiles("index.html")router.GET("/",func(c*gin.Context){c.HTML(http.StatusOK,"index.html",nil)})router.GET("/ws",func(ctx*gin.Context){createWs(ctx,hub)})router.Run(":9999")}五、客户端实现客户端使用原生WebSocket新建index.html文件<!DOCTYPEhtml><htmllang="zh-cn"><head><metacharset="UTF-8"><title>Gin-WebSocket</title><style>html,body{padding:0;margin:0;height:100%;width:100%;display:flex;flex-direction:column;justify-content:center;align-items:center;}#message{display:flex;flex-direction:column;justify-content:center;align-items:center;}</style></head><body><spanid="connected">WebSocket连接中...</span><spanid="onlineClientNum"></span><spanid="historyClientNum"></span><divid="message"></div><div><inputid="input"/><buttononclick="send()">发送</button></div><script>constws=newWebSocket("ws://localhost:9999/ws");//连接成功时触发ws.onopen=()=>{document.getElementById('connected').innerText='WebSocket连接成功'}//接收到消息时触发ws.onmessage=(e)=>{constdata=JSON.parse(e.data)switch(data._event){case"connected":document.getElementById('historyClientNum').innerText='历史:'+data.historyClientNumdocument.getElementById('onlineClientNum').innerText='在线:'+data.onlineClientNumbreak;case"message":constspan=document.createElement('span')span.innerText=data.messagedocument.getElementById('message').appendChild(span)break;default:break;}};//连接关闭时触发ws.onclose=(e)=>{document.getElementById('connected').innerText='WebSocket连接中...'};//发送消息constsend=()=>{constvalue=document.getElementById('input').valueif(value){document.getElementById('input').value=''ws.send(value)}}</script></body></html>六、代码下载gin-ws.zip
暂无评论,我会出手
说点什么
登录用户可以修改和删除评论,可以收到回复的邮件提醒点击登录/注册
最多上传8张图片,仅支持jpg,png格式图片,单张大小5MB以内!
用户名: