douhuang9886 2017-06-08 04:24
浏览 241
已采纳

golang websocket当浏览器意外关闭时如何通知

I am writing a websocket service in golang. The program use gollira websocket to accept ws request, and in each request handler, it listen to rabbitmq queue for messages.

The problem is, when i close browser window, the handler thread is still running, i guess there is an mechanism to be notified when connection disconnected.

I try to listen to channel request.Context().Done(), when i doesn't work.

package main

import (
    "fmt"
    "log"
    "net/http"

    "github.com/gorilla/websocket"
    "github.com/streadway/amqp"
)

var (
    addr     = "localhost:9999"
    upgrader = websocket.Upgrader{
        CheckOrigin: func(r *http.Request) bool { return true },
    }
)

var conn *amqp.Connection

func watch(w http.ResponseWriter, r *http.Request) {
    ns := r.URL.Query().Get("ns")
    if ns == "" {
        return
    }
    c, err := upgrader.Upgrade(w, r, nil)
    if err != nil {
        log.Print("upgrade:", err)
        return
    }
    defer c.Close()

    ch, err := conn.Channel()
    failOnError(err, "Failed to open a channel")
    defer ch.Close()

    err = ch.ExchangeDeclare(
        "notify", // name
        "fanout",           // type
        true,               // durable
        false,              // auto-deleted
        false,              // internal
        false,              // no-wait
        nil,                // arguments
    )
    failOnError(err, "Failed to declare an exchange")

    q, err := ch.QueueDeclare(
        "",    // name
        false, // durable
        false, // delete when usused
        true,  // exclusive
        false, // no-wait
        nil,   // arguments
    )
    failOnError(err, "Failed to declare a queue")

    err = ch.QueueBind(
        q.Name,             // queue name
        ns,                 // routing key
        "dsm_tasks_notify", // exchange
        false,
        nil)
    failOnError(err, "Failed to bind a queue")

    msgs, err := ch.Consume(
        q.Name, // queue
        "",     // consumer
        true,   // auto-ack
        false,  // exclusive
        false,  // no-local
        false,  // no-wait
        nil,    // args
    )
    failOnError(err, "Failed to register a consumer")

    for {
        select {
        case d := <-msgs:
            err = c.WriteMessage(websocket.TextMessage, d.Body)
            if err != nil {
                log.Println("write:", err)
                break
            }
        case <-r.Context().Done():
            log.Println("Disconnect")
            return
        }
    }

}

func failOnError(err error, msg string) {
    if err != nil {
        log.Fatalf("%s: %s", msg, err)
        panic(fmt.Sprintf("%s: %s", msg, err))
    }
}

func main() {
    var err error
    conn, err = amqp.Dial("amqp://guest:guest@localhost:5672/")
    failOnError(err, "Failed to connect to RabbitMQ")
    defer conn.Close()

    http.HandleFunc("/watch", watch)
    log.Fatal(http.ListenAndServe(addr, nil))
}
  • 写回答

1条回答 默认 最新

  • doutan1637 2017-06-08 04:58
    关注

    If the browser cleanly closes the connection, then read on the webssocket connection returns an error. Cleanup the websocket connection as you would on any read error.

    The application must PING the connection and expect the corresponding PONGs to detect other situations. The chat example shows how to send PINGs and receive PONGs.

    本回答被题主选为最佳回答 , 对您是否有帮助呢?
    评论

报告相同问题?

悬赏问题

  • ¥20 求数据集和代码#有偿答复
  • ¥15 关于下拉菜单选项关联的问题
  • ¥15 如何修改pca中的feature函数
  • ¥20 java-OJ-健康体检
  • ¥15 rs485的上拉下拉,不会对a-b<-200mv有影响吗,就是接受时,对判断逻辑0有影响吗
  • ¥15 使用phpstudy在云服务器上搭建个人网站
  • ¥15 应该如何判断含间隙的曲柄摇杆机构,轴与轴承是否发生了碰撞?
  • ¥15 vue3+express部署到nginx
  • ¥20 搭建pt1000三线制高精度测温电路
  • ¥15 使用Jdk8自带的算法,和Jdk11自带的加密结果会一样吗,不一样的话有什么解决方案,Jdk不能升级的情况