go - 如何关闭来自另一个 goroutine 的读取 TCP 连接?
问题描述
我的服务器场景是这样的:一个 io 线程一直在 tcp 连接上进行读取。一段时间后,控制线程可能会由于活动量低或其他原因决定关闭它。如果调用c.Close(),io线程会报如下错误:read tcp xxx->xxx: use of closed network connection。
代码是这样的:
func recv(c net.Conn) {
input := bufio.NewScanner(c)
for input.Scan() {
msg <- input.Text()
...
}
}
//main
conn, err := s.Accept()
...
go recv(conn)
for {
select {
case m := <-msg:
...
case <-timeout:
conn.Close() // oops!
}
}
我也许可以忽略这个错误,但我想知道是否有更好的方法。
解决方案
选项是关闭连接或将读取截止日期设置为过去的时间。无论哪种方式,读取连接都会返回错误。
处理这些错误的最简单方法是统一处理网络连接上读取返回的所有错误:关闭连接,清理与连接相关的资源并继续。关闭连接两次就可以了。
func recv(c net.Conn, msg chan string) {
defer close(msg) // Notify main goroutine that recv is done.
defer c.Close() // Release resources.
input := bufio.NewScanner(c)
// Loop reading lines until read on c returns an error.
// These errors include io.EOF (normal close by the peer),
// the error caused by the main goroutine closing the connection
// and other networking errors.
for input.Scan() {
msg <- input.Text()
}
}
// main
conn, err := s.Accept()
if err != nil {
// handle error
}
msg := make(chan string)
go recv(conn, msg)
for {
select {
case m, ok := <-msg:
if !ok {
// The recv goroutine closed the channel and the connection.
return
}
fmt.Println(m)
case <-timeout:
// Closing the connection causes the recv goroutine to break
// out of the loop. If the recv goroutine received a line of
// text and has yet sent the text to the msg channel, then
// a return from main at this point will cause the recv goroutine
// to block forever. To avoid this, continue looping until until
// the recv goroutine signals that it's done by closing the msg
// channel.
conn.Close()
}
}
}
应用程序可以记录它正在关闭连接并在此之后以特殊方式处理读取错误,但只有在应用程序需要在这种情况下做一些特殊的事情时才这样做。
推荐阅读
- python - Python PEP 是否按照提议/修改的方式实施,还是有回旋余地?
- svg - 如何从 PNG 创建 SVG
- python - os.listdir() 什么都不返回,甚至是一个空列表
- python - 从导入的文本文件数组输出总和、平均值和标准差
- python - Python,从另一个子文件夹导入子文件夹
- javafx - JavaFX - TableView - setItems:TableView 类型中的方法 setItems(ObservableList) 没有向我显示任何内容
- fortran - 子程序分段错误
- unit-testing - 在测试客户端中访问请求容器(event_dispatcher)
- kentico - 关于Kentico10快速批量删除用户
- javascript - srcset 属性的响应图像未按预期工作