2017-10-15 152 views
0

我在Golang中寫了一個TCP客戶端。服務器永遠不會發送任何回覆或任何數據。TCPConn SetWriteDeadline無法正常工作

只要我在給定的超時後無法寫入,我希望客戶端關閉連接。

所以從閱讀中ConnSetWriteDeadline的文檔: 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不是正確的方法,我該怎麼做?
+0

不知道你是什麼意思? Write調用在發送時被阻塞,但它不會因錯誤而超時,據我瞭解應該是這樣?我不關心ACK或任何東西。如果由於任何原因我想返回,通話時間超過1秒。 – Joakim

+1

你確定它實際上在寫入時被阻止嗎?我會檢查堆棧跟蹤。如果不嘗試製作[mcve],因爲這不應該阻止。 – JimB

+0

「_I'm寫一個TCP客戶端......_」TCP沒有客戶端或服務器,這是一個應用程序的概念。 TCP創建對等連接。 –

回答

0

原來這是一個死鎖問題。

我的程序每次在使用扇出模式在messages通道上發送時都使用鎖定。

問題是,當我在Write timeout上返回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 
    }