Golang Go语言中,怎么判断一个 socket 连接是否关闭?
golang 小白求教
Golang Go语言中,怎么判断一个 socket 连接是否关闭?
如果你是问标准库里面的 socket 连接,那么是没有直接的判断方式的。唯有你自己写一个。
方法便是设置 socket 连接的读超时,如果连接读取超时则认为是 socket 已经关闭了
更多关于Golang Go语言中,怎么判断一个 socket 连接是否关闭?的实战系列教程也可以访问 https://www.itying.com/category-94-b0.html
err eof 就是关闭啊
服务器响应心跳, 客户端发送心跳, 除此以外的一切判断方法都会出现线路断开了而报正常.
go 没有提供这样的 api ,一般是往里面写,来判断。
对一个已经关闭的连接读写的话通常会 rest by peer 和 broken pipe
read---->EOF ,已关闭
write---->broken pipe ,已关闭
读超时设置 0 ,然后直接读,error 就是关了
如果是系统接口的 socket 本身,它断了,读和写都会报错 closed
如果是物理意义上的通信链路断,就需要加 keepalive 、心跳包
读超时设置 0 是指不设置超时时间吗?
监控心跳的 socket 和接发数据的 socket 是同一个吗
SetReadDeadline(time.Unix(0,0))
> 如果是物理意义上的通信链路断,就需要加 keepalive 、心跳包
链路层(data link layer)断了,连接还能通过 keepalive 、心跳包恢复,第一眼看到时我觉得不可思议,想了下还是觉得不可思议
可以详细解释一下嘛
这样设置的意思是立即超时?那么接下来的读操作不会直接返回超时 err 嘛?
不是恢复,是判断链路是否还是通的
借楼问个问题,epoll 里面也是用的 keepalive 来触发的吗
“在 golang 中” ×
"在 Linux / Windows 中" √
https://stackoverflow.com/questions/16582303/how-to-check-tcp-peer-is-closed
你要判断这个 socket 是否关闭, 那就只能是这个 socket 的心跳来判断.
这么做的意思是非阻塞读,如果 socket 缓冲区里有东西那就能读到东西,如果没有就直接返回,如果 socket 已经关闭那你调用 read 会得到 error ,调用 SetReadDeadline 是为了防止连接没有关闭然后阻塞在读取上
这样做是 Read 能得到 err 了,但是 socket 如果本身还是活跃的,这就是误杀了
还是我来做课代表吧!
正确的做法:
1. 不要通过调用判断是否断开的方法去判断是否断开(比如 IsClosed )
2. 正常使用 Conn ,根据使用的返回值判断,比如 Read/Write 时返回了 err ,就是断开了
以上两条只是说怎么处理,实际实现 Conn 封装时通常要做的:
1. 单独一个协程处理读
2. 如果需要广播功能,单独一个协程处理写,否则可以不用单独协程、直接写就行
前面已经有人提到 keepalive ,但不够全面,仍需注意:
1. TCP 的 keepalive (传输层,4 层)只是检测连接健康状态,但不能用于判断连接的活跃状态。比如链路通顺、4 层 keepalive 是健康的,但 7 层应用层没有数据交互,这种属于僵尸连接了,对于正常的服务器,是应该踢掉这种长时间不活跃的僵尸连接的。所以 TCP 的 keepalive 选项不能解决僵尸连接的问题
2. 7 层应该自己进行 keepalive 协议包的收发比如 websocket 的 ping/pong ,来相互判断。业务协议活跃时可以节约掉 ping/pong 、一段时间没有业务协议交互再 ping/pong ,但 keepalive 间隔本来也比较大所以即使不节约这点也没关系。
3. 既然 7 层应该有自己的 keepalive ,其实 4 层的 keepalive 就没必要了
还得是课代表
读的时候判断 io.EOF
写的时候判断 broken pipe
#21 有个问题想咨询课代表了,那么如何优雅的主动关闭一个 socket 呢?
不同的服务类型和框架对优雅的定义、代码的封装都不太一样,分类展开了说有点多。。给个详细点的业务类型?
这个课代表,能处
在 Golang 中判断一个 socket 连接是否关闭,通常可以通过以下几种方式来进行:
-
读写操作中的错误处理: 当你尝试从 socket 读取数据或向 socket 写入数据时,如果连接已经关闭,这些操作会返回错误。例如,
Read
方法会返回(0, io.EOF)
表示连接正常关闭,或者返回一个其他错误表示异常关闭。类似地,Write
方法也会返回错误,如果连接已关闭。 -
使用
net.Conn
的Close
方法: 如果你控制了连接的关闭,可以通过调用conn.Close()
来主动关闭连接,并在需要时设置一个标志位来表示连接状态。 -
设置读/写超时: 通过
SetReadDeadline
和SetWriteDeadline
方法可以设置读写操作的超时时间。如果操作在超时时间内没有完成,将返回一个超时错误,你可以根据这个错误来判断连接是否可能存在问题(虽然这并不直接说明连接已关闭,但可能表明连接不再可靠)。 -
心跳机制: 在长时间保持的连接中,实现一个心跳机制(定期发送或接收特定消息)可以帮助检测连接是否仍然活跃。如果心跳消息未能按时到达,可以认为连接可能已经关闭或出现问题。
综合以上方法,通常是通过捕获读写操作的错误来判断 socket 连接是否关闭,同时结合心跳机制等策略来确保连接的可靠性。