大佬教程收集整理的这篇文章主要介绍了GOLANG探测HTTP连接断开,大佬教程大佬觉得挺不错的,现在分享给大家,也给大家做个参考。
考虑基于http的RPC,或者http服务器主动通知客户端的机制,就是@L_404_0@,意思就是客户端发起一个长连接,服务器阻塞忍住不响应直到:
这样客户端和服务器之间RPC的效率就非常高,只有在有事件时才会通知。但是,实际上还有一种情况需要处理:
问题就来了,如何在http Handler中探测客户端断开?例如:
var incoming chan []byte
http.HandleFunc("/polling",func(w http.ResponseWriter,r *http.request) {
SELEct { case b := <- incoming: w.Write(b) case <-time.After(5 * time.Second): w.Write("keepalive") // how to detect TCP disconnect event? } })
可能有以下方式:
r.body
,如果发现断开应该会有错误。w
转换成http.CloseNotifier
,在TCP连接关闭时拿到事件。这种方式是不靠谱的,假设没有Body内容,直接读取检测是否有error:
nn,err := io.Copy(IoUtil.Discard,r.body)
实际上返回的是nn=0
和err=nil
,也就是没有Body,没有错误。因为这个读取的含义是指request结束。
如果读取完Body后再读呢?收到的是io.EOF
,在没有发送Response之前,request已经结束了,所以就是io.EOF
,并不能检测到底层TCP断开。
使用reflect获取底层的TCPConn对象,是知道w http.ResponseWriter
实际上是http.response
:
// A response represents the server side of an http response.
type response struct {
conn *conn
它有个Field就是conn
,再转成TCPConn
就可以Peek。
这样做的风险就是,不同的GOLANG版本,可能会对底层实现进行变更,在升级时会有风险。
Reflect方式始终不是最好的。
另外,还有一种方式,就是用http hijack方式,这种方式虽然是http库提供的接口,但是很多地方注释都说hijack需要特殊处理,因此也不是最好的方式。参考When to use hijack。
在GO1.1提供了http.CloseNotifier
接口,参考Close Notifier,但是也注意会有一些问题,参考net/http: CloseNotifier fails to fire when underlying connection is gone。用法如下:
var incoming chan []byte
http.HandleFunc("/polling",func(w http.ResponseWriter,r *http.request) {
SELEct {
case <- w.(http.CloseNotifier).CloseNotify():
fmt.Println("connection closed")
}
})
实际上,超时机制始终是需要的,加上之前的逻辑,考虑context.Context
取消事件,http-long polling
的完整实现应该是:
func polling(ctx context.Context,incoming chan []bytE) {
http.HandleFunc("/polling",func(w http.ResponseWriter,r *http.request) {
SELEct {
case <- ctx.Done():
fmt.Println("system quit")
case b := <- incoming:
w.Write(b)
case <-time.After(5 * time.Second):
w.Write("keepalive")
case <- w.(http.CloseNotifier).CloseNotify():
fmt.Println("connection closed")
}
})
}
以上是大佬教程为你收集整理的GOLANG探测HTTP连接断开全部内容,希望文章能够帮你解决GOLANG探测HTTP连接断开所遇到的程序开发问题。
如果觉得大佬教程网站内容还不错,欢迎将大佬教程推荐给程序员好友。
本图文内容来源于网友网络收集整理提供,作为学习参考使用,版权属于原作者。
如您有任何意见或建议可联系处理。小编QQ:384754419,请注明来意。