欢迎来到尧图网

客户服务 关于我们

您的位置:首页 > 财经 > 产业 > go 系列实现websocket

go 系列实现websocket

2024/10/25 12:22:18 来源:https://blog.csdn.net/qq_37011724/article/details/141467234  浏览:    关键词:go 系列实现websocket

一、简介

       websocket是个二进制协议,需要先通过Http协议进行握手,从而协商完成从Http协议向websocket协议的转换。一旦握手结束,当前的TCP连接后续将采用二进制websocket协议进行双向双工交互,自此与Http协议无关。

二、websocket demo

ws.go
package mainimport ("fmt""github.com/gorilla/websocket""net/http""time"
)type wsMessage struct {mType intdata  []byte
}type wsConnection struct {wsSocket *websocket.Conn // 底层websocketinChan   chan *wsMessage // 读队列outChan  chan *wsMessage // 写队列state    int             // 连接状态
}func (wsCon *wsConnection) wsReadLoop() {for {if wsCon.state == 1 {return}mType, data, err := wsCon.wsSocket.ReadMessage() // 阻塞if err != nil {fmt.Println("read err: %v", err)continue}msg := &wsMessage{mType,data,}wsCon.inChan <- msg}}func (wsCon *wsConnection) wsWriteLoop() {for {if wsCon.state == 1 {return}msg := <-wsCon.outChan // 阻塞err := wsCon.wsSocket.WriteMessage(msg.mType, msg.data)if err != nil {fmt.Printf("write err: %v", err)continue}}
}func (wsCon *wsConnection) bizLoop() {for {if wsCon.state == 1 {return}// 处理消息msg := <-wsCon.inChanfmt.Println("process msg", string(msg.data))// 返回响应wsCon.outChan <- &wsMessage{mType: 2,data:  []byte(fmt.Sprintf("%s done", string(msg.data))),}}
}func (wsCon *wsConnection) healthLoop() {defer wsCon.wsSocket.Close()for {time.Sleep(3 * time.Second)// 返回响应if err := wsCon.wsSocket.WriteMessage(2,[]byte("心跳检查")); err != nil {fmt.Println("write err: %v", err)wsCon.state = 1return}}
}func wsHandler(resp http.ResponseWriter, req *http.Request) {// 升级websocket协议wsSocket, err := websocket.Upgrade(resp, req, nil, 1024, 1024)if err != nil {fmt.Println("upgrade err: %v", err)}// 一个请求,一个websocket 连接wsCon := &wsConnection{wsSocket: wsSocket,inChan:   make(chan *wsMessage, 1000),outChan:  make(chan *wsMessage, 1000),}go wsCon.wsReadLoop()go wsCon.wsWriteLoop()go wsCon.healthLoop()go wsCon.bizLoop()}func main() {http.HandleFunc("/ws", wsHandler)http.ListenAndServe(":8080", nil)
}
ws.html
<!DOCTYPE html>
<html>
<head><meta charset="utf-8"><script>window.addEventListener("load", function (evt) {var output = document.getElementById("output");var input = document.getElementById("input");var ws;var print = function (message) {var d = document.createElement("div");d.innerHTML = message;output.appendChild(d);};document.getElementById("open").onclick = function (evt) {if (ws) {return false;}ws = new WebSocket("ws://localhost:8080/ws");ws.onopen = function (evt) {print("OPEN");}ws.onclose = function (evt) {print("CLOSE");ws = null;}ws.onmessage = function (evt) {const reader = new FileReader()reader.onload = function (event) {print("RESPONSE: " + event.target.result)}reader.readAsText(evt.data)}ws.onerror = function (evt) {print("ERROR: " + evt.data);}return false;};document.getElementById("send").onclick = function (evt) {if (!ws) {return false;}print("SEND: " + input.value);ws.send(input.value);return false;};document.getElementById("close").onclick = function (evt) {if (!ws) {return false;}ws.close();return false;};});</script>
</head>
<body>
<table><tr><td valign="top" width="50%"><p>Click "Open" to create a connection to the server,"Send" to send a message to the server and "Close" to close the connection.You can change the message and send multiple times.</p><form><button id="open">Open</button><button id="close">Close</button><input id="input" type="text" value="Hello!"><button id="send">Send</button></form></td><td valign="top" width="50%"><div id="output"></div></td></tr>
</table>
</body>
</html>
实现效果

版权声明:

本网仅为发布的内容提供存储空间,不对发表、转载的内容提供任何形式的保证。凡本网注明“来源:XXX网络”的作品,均转载自其它媒体,著作权归作者所有,商业转载请联系作者获得授权,非商业转载请注明出处。

我们尊重并感谢每一位作者,均已注明文章来源和作者。如因作品内容、版权或其它问题,请及时与我们联系,联系邮箱:809451989@qq.com,投稿邮箱:809451989@qq.com