Go 检测TCP连接断开

Go 检测TCP连接断开,go,tcpclient,Go,Tcpclient,问题:客户端需要创建tcp连接,并重新连接,如果由于某种原因连接中断,也可以随时要求断开连接 服务器不在我手中,连接上没有发送数据,只需要建立连接 我使用TCP保持活动的实现,我遵循 func(s*状态)spawnCtrlConnection()(退出chan结构{}){ quit=make(chan结构{},1) go func(地址字符串){ tcpAddr,err:=net.ResolveTCPAddr(“tcp”,s.addr()) 如果错误!=零{ s、 手柄错误(err) 返回 }

问题:客户端需要创建tcp连接,并重新连接,如果由于某种原因连接中断,也可以随时要求断开连接

服务器不在我手中,连接上没有发送数据,只需要建立连接

我使用TCP保持活动的实现,我遵循

func(s*状态)spawnCtrlConnection()(退出chan结构{}){
quit=make(chan结构{},1)
go func(地址字符串){
tcpAddr,err:=net.ResolveTCPAddr(“tcp”,s.addr())
如果错误!=零{
s、 手柄错误(err)
返回
}
conn,err:=net.DialTCP(“tcp”,nil,tcpAddr)
如果错误!=零{
s、 手柄错误(err)
返回
}
延迟函数(){
康涅狄格州关闭
}()
conn.SetKeepAlive(真)
conn.SetKeepAlivePeriod(time.Second*time.Duration(s.WaitInterval))
rawConn,err:=conn.SyscallConn()
如果错误!=零{
s、 手柄错误(err)
返回
}
罗康纳控制中心(
职能(fdPtr uintptr){
fd:=int(fdPtr)
//Ping数量
err=syscall.SetsockoptInt(fd,syscall.IPPROTO\u TCP,syscall.TCP\u keepnt,s.PingAmount)
如果错误!=零{
s、 手柄错误(err)
返回
}
//重试间隔
err=syscall.SetsockoptInt(fd,syscall.IPPROTO_TCP,syscall.TCP_KEEPINTVL,s.RetryInterval)
如果错误!=零{
s、 手柄错误(err)
返回
}
})
为了{
挑选{

case这里是一个建议代码

只要quit没有关闭,当连接关闭时,
for!done
循环将重新连接

conn!=nil的
循环将重复执行select

设置截止日期
放在
读取
之前。当死线开始时,我们确实会收到超时()错误。请注意,我认为当保持活动失败时,我们也可能会收到超时

func(s*状态)spawnCtrlConnection()(退出chan结构{}){
quit=make(chan结构{})
go func(){
瓦多布尔
好了!好了{
//…打开连接。。。
康涅狄格州!=零{
var buf[1]字节
挑选{

case只需为开始连接的
ever循环使用一个
。让Read block和timeout调整它们,当它返回一个连接丢失错误时,只需在循环的开始处返回。您还可以添加一个标志来检测第一次运行,从而确定它是否重新连接。如果服务器发送一个quit命令,不清楚,只需中断循环。在任何情况下在这种情况下,在读取返回之前,您无法退出。读取会在超时期间阻塞,并且在该时间间隔内我将无法断开连接没有“断开连接”这种情况TCP中的消息。您从连接读取,直到它关闭。仅此而已。安装程序使用和保持活动状态。读取连接,直到读取返回错误。仅此而已。
func (s *State) spawnCtrlConnection() (quit chan struct{}) {
    quit = make(chan struct{}, 1)

    go func(addr string) {

        tcpAddr, err := net.ResolveTCPAddr("tcp", s.addr())
        if err != nil {
            s.HandleError(err)
            return
        }

        conn, err := net.DialTCP("tcp", nil, tcpAddr)
        if err != nil {
            s.HandleError(err)
            return
        }

        defer func() {
            conn.Close()
        }()

        conn.SetKeepAlive(true)
        conn.SetKeepAlivePeriod(time.Second * time.Duration(s.WaitInterval))

        rawConn, err := conn.SyscallConn()
        if err != nil {
            s.HandleError(err)
            return
        }

        rawConn.Control(
            func(fdPtr uintptr) {
                fd := int(fdPtr)

                // Ping amount
                err = syscall.SetsockoptInt(fd, syscall.IPPROTO_TCP, syscall.TCP_KEEPCNT, s.PingAmount)
                if err != nil {
                    s.HandleError(err)
                    return
                }
                // Retry interval
                err = syscall.SetsockoptInt(fd, syscall.IPPROTO_TCP, syscall.TCP_KEEPINTVL, s.RetryInterval)
                if err != nil {
                    s.HandleError(err)
                    return
                }
            })

        for {
            select {
            case <-quit:
                return
            default:

                data := make([]byte, 1)
                _, err = conn.Read(data)
                // it blocks here forever and (<- quit will never receive anything)

                // setting explicit timeout doesn't help either, as it will timeout for obvious reason
                //  conn.SetDeadline(time.Now().Add(time.Second * time.Duration(s.WaitInterval)))

                //  if err != nil {
                //      if err, ok := err.(net.Error); ok && err.Timeout() {
                //          fmt.Println("timeout", err.Error())
                //      } else {
                //          fmt.Println("I am here", err.Error())
                //      }
                //  }

                // WHAT SHOULD I CODE


            }
        }
    }()
    return
}