检测TCP连接断开

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

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

我使用TCP的实现保持有效,我遵循了https://thenotexpert.com/golang-tcp-keepalive/

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.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
}

我不明白,我应该编写什么代码来检测断开连接。

可能是我误解了tcp keep-alive的概念。

请帮助。

a65758872 回答:检测TCP连接断开

这是建议的代码。

只要没有关闭退出,for !done循环将在连接关闭后重新连接。

for conn != nil循环将重复执行选择。

SetDeadLine放在Read之前。当死线插入时,我们确实会收到Timeout()错误。请注意,我相信当keep alive失败时,我们也可能会超时。

func (s *State) spawnCtrlConnection() (quit chan struct{}) {
    quit = make(chan struct{})

    go func() {
        var done bool
        for !done {

            // ... open connection ...

            for conn != nil {
                var buf [1]byte
                select {
                case <-quit:
                    conn.Close()
                    conn = nil
                    done = true
                    continue
                default:
                    conn.SetDeadline(time.Now().Add(time.Duration(s.WaitInterval)*time.Second))
                    _,err = conn.Read(buf[:])
                    if err != nil {
                        if err == io.EOF {
                            conn.Close()
                            conn = nil
                            continue
                        }
                        if err,ok := err.(net.Error); ok && err.Timeout() {
                            continue
                        } else {
                            fmt.Println("I am here",err.Error())
                        }
                    }
                }
            }
        }
    }()

    return quit
}
本文链接:https://www.f2er.com/2911699.html

大家都在问