go的websocket应用

  1. 1. 概述
  2. 2. 示例

go的websocket应用

1. 概述

go中会用到websocket,简述一下github.com/go-swagger/go-swaggergithub.com/gorilla/websocket结合使用。

go-swagger会根据swagger文件生成代码的整体结构,能够预定义好很多特性。例如:TLS,middleware等。

websocket在go-swagger中不会预定义,只会被定义为普通http接口,需要对接口重新实现。

2. 示例

func (h *Handler) Websocket(params xterm.WebsocketParams) middleware.Responder {
    logrus.Infoln("Websocket", params)
    var upgrade = websocket.Upgrader{
        Subprotocols: []string{"tty"},
    }
    upgrade.CheckOrigin = func(r *http.Request) bool {
        return true
    }
    id := xid.New().String()
    session := fmt.Sprintf("/%s/%s/%s", params.ProductID, params.DeviceName, id)
    chans := make(chan []byte, 10)
    h.sessions.Store(session, chans)
    h.LogSession()
    return middleware.ResponderFunc(func(rw http.ResponseWriter, pr runtime.Producer) {
        defer func() {
            h.sessions.Delete(session)
            close(chans)
            h.LogSession()
        }()
        webConn, err := upgrade.Upgrade(rw, params.HTTPRequest, nil)
        if err != nil || webConn == nil {
            return
        }
        defer webConn.Close()
        logrus.Infoln("webConn", webConn.RemoteAddr())

        var wg sync.WaitGroup
        done := make(chan struct{})
        wg.Add(1)
        go func() {
            defer wg.Done()
            for {
                select {
                case <-done:
                    return
                case payload, ok := <-chans:
                    if !ok {
                        return
                    }
                    data := append([]byte{byte(Output)}, payload...)
                    err = webConn.WriteMessage(websocket.BinaryMessage, data)
                    if err != nil {
                        logrus.WithError(err).Errorln("WriteMessage error")
                        return
                    }
                }
            }
        }()
        wg.Add(1)
        go func() {
            defer wg.Done()
            data := []byte{0x30, 0x0d}
            _ = h.ReadMessage(data, params.ProductID, params.DeviceName)
            for {
                _, data, err = webConn.ReadMessage()
                if err != nil {
                    done <- struct{}{}
                    logrus.WithError(err).Errorln("ReadMessage error")
                    return
                }
                err = h.ReadMessage(data, params.ProductID, params.DeviceName)
                if err != nil {
                    continue
                }
            }
        }()
        wg.Wait()
    })
}

当客户端定义了子协议,服务端也需要进行定义,否则会有1006错误

var upgrade = websocket.Upgrader{
        Subprotocols: []string{"tty"},
    }

跨域检查,当跨域时通过检查

upgrade.CheckOrigin = func(r *http.Request) bool {
        return true
    }

转载请注明来源,欢迎对文章中的引用来源进行考证,欢迎指出任何有错误或不够清晰的表达。可以在下面评论区评论,也可以邮件至 wind.kaisa@gmail.com

💰

×

Help us with donation