Von*_*onC 60
该线程" 的最佳方式可靠地检测TCP连接被关闭 ",使用net.Conn了" c"(也可见于utils/ping.go或locale-backend/server.go或许多其他情况下):
one := make([]byte, 1)
c.SetReadDeadline(time.Now())
if _, err := c.Read(one); err == io.EOF {
l.Printf(logger.LevelDebug, "%s detected closed LAN connection", id)
c.Close()
c = nil
} else {
var zero time.Time
c.SetReadDeadline(time.Now().Add(10 * time.Millisecond))
}
Run Code Online (Sandbox Code Playgroud)
为了检测超时,它建议:
if neterr, ok := err.(net.Error); ok && neterr.Timeout() {
...
Run Code Online (Sandbox Code Playgroud)
min*_*omi 14
只是尝试从中读取,如果它关闭它会抛出错误.如果你愿意,可以优雅地处理!
为了放弃太多的风险:
func Read(c *net.Conn, buffer []byte) bool {
bytesRead, err := c.Read(buffer)
if err != nil {
c.Close()
log.Println(err)
return false
}
log.Println("Read ", bytesRead, " bytes")
return true
}
Run Code Online (Sandbox Code Playgroud)
以下是使用net包制作小型TCP"聊天服务器"的一个很好的介绍:
小智 6
经过一段时间的努力后,这里有一个 POSIX 解决方案,用于MSG_PEEK防止耗尽缓冲区并导致竞争条件。这可以让你检查 TCP 套接字的 READ 部分是否仍然从另一个 goroutine 打开:
func connCheck(conn net.Conn) error {
var sysErr error = nil
rc, err := conn.(syscall.Conn).SyscallConn()
if err != nil { return err }
err = rc.Read(func(fd uintptr) bool {
var buf []byte = []byte{0}
n, _, err := syscall.Recvfrom(int(fd), buf, syscall.MSG_PEEK | syscall.MSG_DONTWAIT)
switch {
case n == 0 && err == nil:
sysErr = io.EOF
case err == syscall.EAGAIN || err == syscall.EWOULDBLOCK:
sysErr = nil
default:
sysErr = err
}
return true
})
if err != nil { return err }
return sysErr
}
Run Code Online (Sandbox Code Playgroud)
这是基于上面的 mysql#connCheck,但是它执行了 1 字节的读取系统调用,这可能会与尝试读取流的其他 goroutine 发生冲突。
| 归档时间: |
|
| 查看次数: |
61027 次 |
| 最近记录: |