首頁 > 後端開發 > Golang > 主體

golang tcp close 報錯

PHPz
發布: 2023-05-13 11:24:37
原創
442 人瀏覽過

最近在使用 Golang 編寫 TCP 通訊程式時,遇到了一個奇怪的 Close 錯誤,將其記錄下來分享一下。

背景

在我寫的 TCP 通訊程式中,使用了 Go 標準庫中的 net 包,透過 DialTCP 函數連接到伺服器。在通訊結束後,使用 Close 方法關閉連線。在大多數情況下,這個過程都是成功的。但有時候,在呼叫 Close 方法時,會拋出一個奇怪的錯誤,程式崩潰了。

錯誤描述

-Close tcp 呼叫中的錯誤-
描述: reset by peer`
錯誤日誌中顯示,在使用Close 方法關閉連線時,報錯“reset by peer”,也就是伺服器端主動關閉了連線。

排查

第一步,我查看了原始程式碼,確認在呼叫 Close 方法之前,連線並沒有關閉。第二步,我試著從程式碼的角度分析這個問題,接著可以排除程式碼的缺陷。

第三步,我搜尋了一下這個問題,發現了相似的案例。在開源社群 Github 上,有很多人也遇到了類似的問題。有些人認為這是作業系統對 TCP 規範的實作有問題,有些人則認為是網路卡驅動的錯誤。我看到這些資訊之後,稍微查閱了一下關於 TCP 協定的規範,發現對於連線關閉的操作,確實有一個 TIME_WAIT 的時間等待。

具體來說,一個 TCP 連線關閉後,作業系統會等待一定的時間,直到確認這個連線已經完全關閉,才會釋放相關的資源。這個時間通常為 2MSL(Maximum Segment Lifetime) ,在 Linux 上預設為 60 秒。如果在這個等待時間內,有新的相同位址和連接埠的連接請求時,會觸發 RST 段,也就是對方提前關閉連接,此時就會出現「reset by peer」的錯誤。

那麼,這樣的問題該如何解決呢?

解決

對於這個問題,有兩種解決方法:

  1. 延長 TIME_WAIT 時間。

修改 Linux 核心的參數,可以延長 TIME_WAIT 時間,更長的時間等待可以確保連線被完全關閉。當然,在這個延長的時間內,系統中長時間處於 TIME_WAIT 狀態的連線數量也會增加。

  1. 設定 SO_REUSEADDR 選項,使連接位址可重複使用。

在關閉連線時,開啟 SO_REUSEADDR 選項,使得連線位址可重複使用。這樣,在連線關閉後,下一次新的連線就可以直接復用原先的位址,避免了出現「reset by peer」的錯誤。具體實作方法如下:

conn, err := net.DialTCP("tcp", nil, tcpAddr)
err = conn.SetReuseAddr(true)
err = conn.Close()
登入後複製

總結

以上就是我在使用 Golang 寫 TCP 通訊程式時,遇到的一個奇怪 Close 錯誤的案例。原因是 TCP 規範中需要等待的 TIME_WAIT 時間,導致連線沒有即時釋放。透過延長等待時間或開啟 SO_REUSEADDR 選項,我們可以避免這類錯誤的發生。同時,這也提醒我們在進行網路程式設計時,需要注意 TCP 規範中的一些細節,以避免不必要的錯誤。

以上是golang tcp close 報錯的詳細內容。更多資訊請關注PHP中文網其他相關文章!

來源:php.cn
本網站聲明
本文內容由網友自願投稿,版權歸原作者所有。本站不承擔相應的法律責任。如發現涉嫌抄襲或侵權的內容,請聯絡admin@php.cn
熱門教學
更多>
最新下載
更多>
網站特效
網站源碼
網站素材
前端模板
關於我們 免責聲明 Sitemap
PHP中文網:公益線上PHP培訓,幫助PHP學習者快速成長!