2016-11-29 336 views
2

我確實有一個進程從第二本地進程接收數據。我需要測試連接錯誤是否處理得當,以及連接錯誤是否自動重新連接並在斷開連接後繼續接收數據。如何在GO中測試TCP斷開

爲此,我試圖使它突然斷開或將TCP連接置於單元測試的錯誤狀態。 如在this question中看到的,以檢查連接是否已關閉,我正在檢查數據來測試它是否返回錯誤。 我不知道如何:

  • 關閉連接非正常
  • 使其處於錯誤狀態

這是我的數據接收器的本質:

import (
     "bufio" 
     "encoding/json" 
     "fmt" 
     "io" 
     "net" 
    ) 

    type Message struct { 
     ID string `json:"id"` 
    } 

    func ReceiveData(listener Listener) { 
     var tcpConn net.Conn 
     var addr string = "127.0.0.1:9999" 
     tcpConn, err := net.Dial("tcp", addr) 
     socketReader := bufio.NewReader(tcpConn) 
     decoder := json.NewDecoder(socketReader) 

     for { 
      var msg Message 
      if err := decoder.Decode(&msg); err == io.EOF { 
       listener.ProcessUpdate(Message{}, fmt.Errorf("Received EOF"), nil) 
       tcpConn = nil 
       return 
      } else if err != nil { 
       listener.ProcessUpdate(Message{}, nil, fmt.Errorf("Error decoding message: %s", err.Error())) 
       tcpConn = nil 
       return 
     } 

     // process message 
     _ = msg 

     // Test disconnection 
     // This does not disconnect: 
     // tcpConn = nil 
     // This does but gracefully: 
     // tcpConn.Close() 
    } 

我不想嘲笑TCP連接,因爲我想試試真正的數據生產者。如果需要,我會看看它。

+0

究竟什麼叫收盤意思連接「非常」? – JimB

+0

意外斷開,人們拔掉電纜,另一端斷電,tcp信息格式不正確。我懷疑大多數這些會產生超時,我不知道'tcpConn.Read()'可能產生的所有錯誤。 –

+0

如果您希望遠程端模擬斷開連接,如拉動電纜或斷開電源,請確保Keepalive被禁用並停止響應。如果您想以其他各種方式斷開連接,則需要在網絡的較低級別執行此操作。 – JimB

回答

1

一種解決方案是一個deadline設置爲TCP連接本身:

tcpConn.SetDeadline(time.Now()) 

後來這將觸發超時錯誤,可以被捕獲:

err := decoder.Decode(&msg); 
if err != nil { 
    if neterr, ok := err.(net.Error); ok && neterr.Timeout() { 
     fmt.Errorf("TCP timeout : %s", err.Error()) 
    } else { 
     fmt.Errorf("Received error decoding message: %s", err.Error()) 
    } 
}