TCPConn SetWriteDeadline无效

时间:2017-10-15 20:11:03

标签: networking go tcp network-programming timeout

我正在 Golang 中编写TCP客户端。服务器永远不会发送任何回复或任何数据。

一旦我在给定超时后写入失败,我希望客户端关闭连接。

因此,请阅读SetWriteDeadlineConn的文档: 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做错了什么?
  • 如果Write没有在给定的超时时间内完成,我想杀死连接,如果SetWriteDeadline不是正确的方法,我该怎么办?

1 个答案:

答案 0 :(得分:0)

这结果是一个僵局问题。

我的程序每次使用扇出模式在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
    }