代码之家  ›  专栏  ›  技术社区  ›  Ralph java.is.for.desktop

在浏览器关闭时关闭go服务器

  •  2
  • Ralph java.is.for.desktop  · 技术社区  · 7 年前

    我在go中编写了一个小的支票簿分类账,作为在本地主机中运行的服务器,并将默认浏览器打开到一个小的web应用程序前端( https://bitbucket.org/grkuntzmd/checks-and-balances )

    要在关闭浏览器选项卡时自动关闭服务器,我让浏览器每隔几秒钟调用一个“心跳”url。如果心跳未到达,服务器将使用 (*Server) Shutdown 停止奔跑。

    有没有办法用上下文做同样的事情( https://golang.org/pkg/context/ )?这是我从观看中得到的理解 this justforfunc的一集,如果客户端取消请求,则将通知传递给处理程序的上下文。

    2 回复  |  直到 6 年前
        1
  •  3
  •   Zippo    7 年前

    您可以利用 server-sent events .

    服务器发送事件是一种web技术,浏览器在其中发出http请求并保持连接打开以从服务器接收事件。这可以通过在关闭与事件源的连接时关闭服务器来代替对重复心跳请求的需要。

    以下是go中的一个基本服务器实现:

    package main
    
    import (
        "fmt"
        "log"
        "net/http"
        "time"
    )
    
    func main() {
        http.HandleFunc("/heartbeat", func(w http.ResponseWriter, r *http.Request) {
            w.Header().Set("Content-Type", "text/event-stream")
            w.Header().Set("Cache-Control", "no-cache")
            w.Header().Set("Connection", "keep-alive")
    
            flusher, ok := w.(http.Flusher)
            if !ok {
                http.Error(w, "your browser doesn't support server-sent events")
                return
            }
    
            // Send a comment every second to prevent connection timeout.
            for {
                _, err := fmt.Fprint(w, ": ping")
                if err != nil {
                    log.Fatal("client is gone, shutting down")
                    return
                }
                flusher.Flush()
                time.Sleep(time.Second)
            }
        })
        fmt.Println(http.ListenAndServe(":1323", nil))
    }
    

    using server-sent events 为客户提供指导。

        2
  •  2
  •   Cerise Limón    7 年前

    从页面打开WebSocket连接。在服务器上,关闭WebSocket连接时退出:

    func wsHandler(w http.ResponseWriter, r *http.Request) {
        conn, err := upgrader.Upgrade(w, r, nil)
        if err != nil {
            log.Println(err)
            return
        }
        defer c.Close()
    
        // Shutdown on exit from handler
        defer server.Shutdown(context.Background())
    
        // Read  messages from client. NextReader returns an error
        // when the client shuts down.
        for {
            if _, _, err := c.NextReader(); err != nil {
                break
            }
        }
     }
    

    将这一行代码添加到客户端应用程序:

     var conn = new WebSocket("ws://" + document.location.host + "/ws");
    

    确保 conn 具有页的生存期。

    这与另一个答案中建议的sse解决方案有些相似,但它的优点是可以在更多的浏览器中工作。

    不需要发送心跳,因为这是在本地主机上。