让我们假设客户端通过http上传大量图片,网络连接速度很慢,他打开到服务器的连接,开始写入数据,突然由于网络问题失去了连接。如果处理程序函数尚未调用,我如何在服务器上检测到这一点。我找到的解决方案是检查连接状态。但问题是它不是可伸缩的,因为许多goroutine将与全局变量交互。还有没有更好的解决方案?
package main
import (
"fmt"
"log"
"net"
"net/http"
)
// current state of connections
var connStates = make(map[string]http.ConnState)
func main() {
http.HandleFunc("/", func(w http.ResponseWriter, r *http.Request) {
fmt.Println("got new request")
fmt.Println(connStates)
})
srv := &http.Server{
Addr: ":8080",
ConnState: func(conn net.Conn, event http.ConnState) {
if event != http.StateClosed {
connStates[conn.RemoteAddr().String()] = event
} else {
if connStates[conn.RemoteAddr().String()] == http.StateActive {
fmt.Println("client cancelled request")
}
delete(connStates, conn.RemoteAddr().String())
}
},
}
log.Fatal(srv.ListenAndServe())
}发布于 2019-04-29 20:16:45
您可以在处理程序中使用context,例如,这将检测客户端何时断开连接并返回以及 http.StatusPartialContent除了在您可以拥有日志记录逻辑的地方调用 someCleanup() 之外。
https://play.golang.org/p/5Yr_HBuyiZW
func helloWorld(w http.ResponseWriter, r *http.Request) {
ctx := r.Context()
ch := make(chan struct{})
go func() {
time.Sleep(5 * time.Second)
fmt.Fprintln(w, "Hello World!")
ch <- struct{}{}
}()
select {
case <-ch:
case <-ctx.Done():
http.Error(w, ctx.Err().Error(), http.StatusPartialContent)
someCleanUP()
}}
发布于 2019-04-29 19:12:13
如果你只需要日志,你甚至可以简化代码:
srv := &http.Server{
Addr: ":8080",
ConnState: func(conn net.Conn, event http.ConnState) {
log.Printf("addr: %s, changed state to: %s", conn.RemoteAddr(), event.String())
},
}该回调将在conn的每次更改时触发
https://stackoverflow.com/questions/55884054
复制相似问题