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.

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

报告相同问题?

悬赏问题

  • ¥15 drone 推送镜像时候 purge: true 推送完毕后没有删除对应的镜像,手动拷贝到服务器执行结果正确在样才能让指令自动执行成功删除对应镜像,如何解决?
  • ¥15 求daily translation(DT)偏差订正方法的代码
  • ¥15 js调用html页面需要隐藏某个按钮
  • ¥15 ads仿真结果在圆图上是怎么读数的
  • ¥20 Cotex M3的调试和程序执行方式是什么样的?
  • ¥20 java项目连接sqlserver时报ssl相关错误
  • ¥15 一道python难题3
  • ¥15 牛顿斯科特系数表表示
  • ¥15 arduino 步进电机
  • ¥20 程序进入HardFault_Handler