Skip to content

gorilla/websocket

go get github.com/gorilla/websocket

参考

Upgrader

Upgrader指定用于将 HTTP 连接升级到 WebSocket 连接

type Upgrader struct {
    HandshakeTimeout time.Duration
    ReadBufferSize, WriteBufferSize int
    WriteBufferPool BufferPool
    Subprotocols []string
    Error func(w http.ResponseWriter, r *http.Request, status int, reason error)
    CheckOrigin func(r *http.Request) bool
    EnableCompression bool
}
  • HandshakeTimeout: 握手完成的持续时间
  • ReadBufferSizeWriteBufferSize:以字节为单位指定I/O缓冲区大小。如果缓冲区大小为零,则使用HTTP服务器分配的缓冲区
  • CheckOrigin : 函数应仔细验证请求来源 防止跨站点请求伪造

这里一般会设置下CheckOrigin来解决跨域问题,也可以var upgrader = websocket.Upgrader{} // use default options使用默认配置。

Conn

Conn类型表示WebSocket连接,这个结构体的组成包括两部分,写入字段(Write fields)和 读取字段(Read fields)

type Conn struct {
 conn        net.Conn
 isServer    bool
 ...

 // Write fields
 writeBuf      []byte        
 writePool     BufferPool
 writeBufSize  int
 writer        io.WriteCloser 
 isWriting     bool           
 ...
 // Read fields
 readRemaining int64
 readFinal     bool  
 readLength    int64 
 messageReader *messageReader 
 ...
}

isServer 字段来区分我们是否用Conn作为客户端还是服务端,也就是说说gorilla/websocket中同时编写客户端程序和服务器程序,但是一般是Web应用程序使用单独的前端作为客户端程序。

服务端示例

以gin框架为例

var upgrader = websocket.Upgrader{} // use default options

func main() {
 route := gin.Default()
 router.GET("/ws", func(c *gin.Context) {
  wsHandler(c.Writer, c.Request)
 })
 route.Run("localhost:8080")
}

func wsHandler(w http.ResponseWriter, r *http.Request) {
 //转换为升级为websocket
 conn, err := upGrader.Upgrade(w, r, nil)
 //释放连接
 defer conn.Close()

 for {
  //接收消息
  messageType, message, err := conn.ReadMessage()
  log.Println("server receive messageType", messageType, "message", string(message))
  //发送消息
  err = conn.WriteMessage(messageType, []byte("pong"))
 }
}

客户端示例

以gin框架为例

 //服务器地址 websocket 统一使用 ws://
 url := "ws://localhost:8080/ws"
 //使用默认拨号器,向服务器发送连接请求
 conn, _, err := websocket.DefaultDialer.Dial(url, nil)
 //关闭连接
 defer conn.Close()
 //发送消息
 go func() {
  for {
   err := conn.WriteMessage(websocket.BinaryMessage, []byte("ping"))
   time.Sleep(time.Second * 2)
  }
 }()
 //接收消息
 for {
  _, data, err := conn.ReadMessage()
  fmt.Println("client receive message: ", string(data))
 }