golang实现WebSocket的商业化使用的开发逻辑(1)

WebSocket是什么

WebSocket 是一种在单个 TCP 连接上进行全双工通信的协议。其最大特点之一就是:服务器可以主动向客户端推送信息,客户端也可以主动向服务器发送信息,是真正的双向平等对话。
开发前期准备(默认已经安装了golang语言环境)
我这里通过两个库来实现整个WebSocket的开发,这两个库分别是gingorilla/websocket。这里有两种方法来获取这两个库,其一就是用go get,其二是使用git bash中的git clone拉取。我使用的是第二种方法,具体使用方法如下。
  • 拉取gorilla/websocketGOPATHsrc下的github.com目录里面
    git clone https://github.com/gorilla/websocket

  • 拉取gin-gonic/ginGOPATHsrc下的github.com目录里面
    git clone https://github.com/gin-gonic/gin

WebSocket 简单使用开发(内部并发不安全,服务端server) 开发逻辑
  • 【golang实现WebSocket的商业化使用的开发逻辑(1)】定义将HTTP升级成WebSocket的全局变量upgrade,并默认允许跨域。
    var ( upgrade = &websocket.Upgrader{ // 允许跨域 CheckOrigin: func(r *http.Request) bool { return true }, } )

  • 确定服务的基本结构,即确定main函数的结构
    func main(){ r := gin.Default() r.GET("/test",func(c *gin.Context){}) err := r.Run(":1234") if err != nil{ return } }

    这就是用gin框架搭载的一个简单HTTP服务,这里可以看出WebSocket就是由HTTP进行升级得到的。现在我们只要把r.GET()里面的func(c *gin.Context){}进行封装,即可完善整个服务。
  • 完善内部逻辑
    func handler(c *gin.Context) { // 定义两个变量,其一就是*websocket.Conn,其二就是error var ( conn *websocket.Conn errerror ) // 赋值变量,这里就用到了前面定义的upgrade // conn这结构体内有许多功能,可以都尝试一下,当一般常使用: // conn.ReadMessage() // conn.WriteMessage() // conn.Close() if conn, err = upgrade.Upgrade(c.Writer, c.Request, nil); err != nil { return } // 为了防止忘记关闭WebSocket连接,使用defer defer func(conn *websocket.Conn) { if err = conn.Close(); err != nil { return } }(conn) // 这里只处理客户端传什么就返回什么 for { // 定义数据变量 var ( msgType int// 数据类型 data[]byte // 数据 errMsgerror//错误信息 ) // 接收数据 if msgType, data, errMsg = conn.ReadMessage(); errMsg != nil { break } // 响应数据 if errMsg = conn.WriteMessage(msgType,data); errMsg != nil{ break } } }

    这里解释一下为什么说这个使用为什么内部线程不安全,因为conn.ReadMessage()conn.WriteMessage()这两个接口是并发不安全的,它们在同一时刻不能被不同线程同时调用,否者会使服务中断。具体情况可以在函数里面写过几个goroutine就可以深刻体会它们的这种不安全。这就导致了一种情况做不到,就是若是想做一个心跳机制,这里就不能再开一个goroutine
  • main函数调整
    func main() { r := gin.Default() r.GET("/test", handler) err := r.Run(":1234") if err != nil { return } }

    只要把r.GET()里面的func(c *gin.Context){}提到成handler函数即可。
完整代码如下
package mainimport ( "github.com/gin-gonic/gin" "golang.org/websocket" "net/http" )var ( upgrade = &websocket.Upgrader{ CheckOrigin: func(r *http.Request) bool { return true }, } )func handler(c *gin.Context) { // 定义两个变量,其一就是*websocket.Conn,其二就是error var ( conn *websocket.Conn errerror ) // 赋值变量,这里就用到了前面定义的upgrade // conn这结构体内有许多功能,可以都尝试一下,当一般常使用: // conn.ReadMessage() // conn.WriteMessage() // conn.Close() if conn, err = upgrade.Upgrade(c.Writer, c.Request, nil); err != nil { return } // 为了防止忘记关闭WebSocket连接,使用defer defer func(conn *websocket.Conn) { if err = conn.Close(); err != nil { return } }(conn) // 这里只处理客户端传什么就返回什么 for { // 定义数据变量 var ( msgType int// 数据类型 data[]byte // 数据 errMsgerror//错误信息 ) // 接收数据 if msgType, data, errMsg = conn.ReadMessage(); errMsg != nil { break } // 响应数据 if errMsg = conn.WriteMessage(msgType,data); errMsg != nil{ break } } }func main() { r := gin.Default() r.GET("/test", handler) err := r.Run(":1234") if err != nil { return } }

WebSocket 商业化使用开发 (内部并发安全,服务端server) 逻辑结构图 golang实现WebSocket的商业化使用的开发逻辑(1)
文章图片

说明:
封装 服务函数封装 完整代码

    推荐阅读