我正在使用 Golang 编写一个TCP客户端。服务器将永远不会发送任何答复或任何数据。

给定的超时后,如果我无法写入,我希望客户端关闭连接。

因此,通过阅读SetWriteDeadline中的Conn文档:
https://golang.org/pkg/net/#Conn

    // SetWriteDeadline sets the deadline for future Write calls
    // and any currently-blocked Write call.
    // Even if write times out, it may return n > 0, indicating that
    // some of the data was successfully written.
    // A zero value for t means Write will not time out.
    SetWriteDeadline(t time.Time) error

从上面的描述中,我可以这样使用它:
...
for {
    select {
    case msg := <-messages:
        conn.SetWriteDeadline(time.Now().Add(1 * time.Second))

        // When server goes away this just blocks forever. No timeout!
        n, err := conn.Write(msg.ByteArray())
        if err != nil {
            return err
        }
        log.Printf("Sent %v bytes\n", n)
    }
}
...

但是,如果服务器消失,则永远不会触发超时,相反,Write调用将永远阻塞。
  • SetWriteDeadline在做什么?
  • 如果无论在什么时间内写入都没有完成,我想终止连接,如果SetWriteDeadline不是执行此操作的正确方法,我该怎么做?
  • 最佳答案

    原来这是一个僵局问题。

    我的程序每次使用Fanout模式在messages通道上发送时都使用锁。

    问题是,当我在写入超时时返回err时,有一个defer调用试图锁定同一Mutex。因为我没有得到输出,所以我以为超时就不会触发。

    defer func() {
        thing.ThatCreatedDeadlock()
        log.Println("Expected to see this")
    }
    

    因此,直接登录Write错误将使这一点显而易见:
        n, err := conn.Write(msg.ByteArray())
        if err != nil {
            log.Println(err)
            return err
        }
    

    关于networking - TCPConn SetWriteDeadline无法正常工作,我们在Stack Overflow上找到一个类似的问题:https://stackoverflow.com/questions/46759513/

    10-11 08:55