gobwas-ws clean conn close

Viewed 339

I use high-level structures to create a ws server.

func wsHandler(w http.ResponseWriter, r *http.Request) {
    re := regexp.MustCompile(`^\/ws\/([0-9a-zA-Z]+)\/*`)

    match := re.FindStringSubmatch(r.URL.Path)
    if len(match) != 2 {
        http.NotFound(w, r)
        return
    }

    conn, _, _, err := ws.UpgradeHTTP(r, w)
    if err != nil {
        log.Printf("gobwas/ws: %s", err)
    }
    go func() {
        defer conn.Close()

        channels.Lock()
        channels.Channels[match[1]] = append(channels.Channels[match[1]], &conn)
        channels.Unlock()

        for {
            msg, op, err := wsutil.ReadClientData(conn)
            if err != nil {
                if err != io.EOF {
                    log.Printf("gobwas/ws/wsutil: %s", err)
                }
                break
            }

            if len(msg) > 0 {
                go sendMessage(&conn, op, match[1], msg)
            }
        }

        deleteConn(&conn, match[1])
    }()
}

Then, when I implement a graceful disconnection, then with the usual conn.Close (), the connection simply breaks outside the protocol. I use the following code to close:

func onShutdown() {
    channels.RLock()
    for _, channel := range channels.Channels {
        for _, conn := range channel {
            if err := ws.WriteFrame(*conn, ws.NewCloseFrame(ws.NewCloseFrameBody(ws.StatusNormalClosure, "Server shutdown"))); err != nil {
                fmt.Println(err)
            }

            (*conn).Close()
        }
    }
    channels.RUnlock()
}

And even if I wait for a response from the client and then close the connection, then anyway, the client fixes the disconnection. (The client is the browser and JS WebSocket). Sample JS code:

var socket = new WebSocket(`${location.protocol === "https:" ? "wss:" : "ws:"}//${window.location.host}/ws/valid`);

socket.onclose = function (event) {
    if (event.wasClean) {
        console.log('Clean');
    } else {
        console.log('disconnect');
    }
    console.log('Code: ' + event.code + ' reason: ' + event.reason);
};
0 Answers
Related