我有这个API扫描司机的位置,并通过web-socket发送他们每1秒。问题是,当客户端断开连接时,无法逃脱循环。它似乎永远活着。我正在使用Gin与nhooyr websocket库。
var GetDriverLocations = func(c *gin.Context) {
wsoptions := websocket.AcceptOptions{InsecureSkipVerify: true}
wsconn, err := websocket.Accept(c.Writer, c.Request, &wsoptions)
if err != nil {
return
}
defer wsconn.Close(websocket.StatusInternalError, "the sky is falling")
driverLocation := &models.DriverLocation{}
ticker := time.NewTicker(time.Second)
defer ticker.Stop()
for {
select {
case <-ticker.C:
case <-c.Request.Context().Done():
fmt.Println("done") //this never gets printed
return
}
coords, err := driverLocation.GetDrivers()
if err != nil {
break
}
err = wsjson.Write(c.Request.Context(), wsconn, &coords)
if websocket.CloseStatus(err) == websocket.StatusNormalClosure {
break
}
if err != nil {
break
}
}
fmt.Println("conn ended") //this never gets printed
}
我也试过这个循环,但也有同样的问题:
for range ticker.C{
coords, err := driverLocation.GetDrivers()
if err != nil {
break
}
err = wsjson.Write(c.Request.Context(), wsconn, &coords)
if websocket.CloseStatus(err) == websocket.StatusNormalClosure {
break
}
if err != nil {
break
}
}
由于网络连接被nhooyr websocket库从net/http服务器劫持,上下文c.Request.Context()
直到处理程序返回才被取消。
调用CloseRead获取连接关闭时被取消的上下文。在循环中使用该上下文。
var GetDriverLocations = func(c *gin.Context) {
wsoptions := websocket.AcceptOptions{InsecureSkipVerify: true}
wsconn, err := websocket.Accept(c.Writer, c.Request, &wsoptions)
if err != nil {
return
}
defer wsconn.Close(websocket.StatusInternalError, "")
ctx := wsconn.CloseRead(c.Request.Context())
driverLocation := &models.DriverLocation{}
ticker := time.NewTicker(time.Second)
defer ticker.Stop()
for {
select {
case <-ticker.C:
case <-ctx.Done():
return
}
coords, err := driverLocation.GetDrivers()
if err != nil {
break
}
err = wsjson.Write(c.Request.Context(), wsconn, &coords)
if err != nil {
break
}
}
}