2 回答

TA貢獻(xiàn)1725條經(jīng)驗(yàn) 獲得超8個(gè)贊
套接字 api 不允許您訪問連接狀態(tài)。您可以通過各種方式從內(nèi)核(/proc/net/tcp[6]
例如在 linux 上)查詢當(dāng)前狀態(tài),但這并不能保證進(jìn)一步發(fā)送會(huì)成功。
我在這里有點(diǎn)困惑。我的客戶只發(fā)送數(shù)據(jù)。除了確認(rèn)數(shù)據(jù)包外,服務(wù)器不會(huì)返回任何內(nèi)容。閱讀似乎不是確定連接狀態(tài)的合適方法,因?yàn)橛凶⒁忾喿x。
套接字 API 被定義為通過讀取返回 0 字節(jié)來檢測關(guān)閉的連接。這就是它的工作方式。在 Go 中,這被轉(zhuǎn)換為 Read 返回io.EOF
。這通常是檢測斷開連接的最快方法。
那么我是否應(yīng)該只發(fā)送并處理發(fā)生的任何錯(cuò)誤?如果是這樣,這是一個(gè)問題,因?yàn)槲矣^察到在嘗試通過損壞的管道發(fā)送時(shí),我通常根本不會(huì)收到任何錯(cuò)誤——這似乎完全錯(cuò)誤
如果您仔細(xì)觀察 TCP 的工作原理,就會(huì)發(fā)現(xiàn)這是預(yù)期的行為。如果連接在遠(yuǎn)程端關(guān)閉,那么您的第一次發(fā)送將觸發(fā)來自服務(wù)器的 RST,完全關(guān)閉本地連接。您要么需要從連接中讀取數(shù)據(jù)以檢測關(guān)閉,或者如果您再次嘗試發(fā)送,您將收到一個(gè)錯(cuò)誤(假設(shè)您等待數(shù)據(jù)包來回的時(shí)間足夠長),例如 linux 上的“管道損壞” .
澄清一下......我可以撥號,拔下以太網(wǎng)電纜,然后仍然沒有錯(cuò)誤地發(fā)送。顯然,消息沒有通過,但我沒有收到任何錯(cuò)誤
如果連接確實(shí)中斷了,或者服務(wù)器完全沒有響應(yīng),那么您將數(shù)據(jù)包發(fā)送到任何地方。TCP 堆棧無法區(qū)分真正慢的數(shù)據(jù)包、數(shù)據(jù)包丟失、擁塞或連接斷開之間的區(qū)別。系統(tǒng)需要等待重傳超時(shí),并在失敗之前重試數(shù)據(jù)包多次。僅重試的標(biāo)準(zhǔn)配置可能需要 13 到 30 分鐘才能觸發(fā)錯(cuò)誤。
你可以在你的代碼中做的是
開啟?;?。這將更快地通知您連接斷開,因?yàn)榭臻e連接始終在測試中。
從套接字讀取。要么進(jìn)行并發(fā)讀取,要么使用 select/poll/epoll 檢查要先讀取的內(nèi)容(Go 通常使用第一個(gè))
為所有內(nèi)容設(shè)置超時(shí)(Go 中的截止日期)。
如果您不希望從連接中獲得任何數(shù)據(jù),那么在 Go 中檢查關(guān)閉的連接非常容易;調(diào)度一個(gè) goroutine 從連接中讀取,直到出現(xiàn)錯(cuò)誤。
notify := make(chan error)
go func() {
buf := make([]byte, 1024)
for {
n, err := conn.Read(buf)
if err != nil {
notify <- err
return
}
if n > 0 {
fmt.Println("unexpected data: %s", buf[:n])
}
}
}()

TA貢獻(xiàn)1877條經(jīng)驗(yàn) 獲得超6個(gè)贊
按照設(shè)計(jì),沒有“TCP 連接狀態(tài)”這樣的東西。只有當(dāng)你發(fā)送一些東西時(shí)才會(huì)發(fā)生什么。沒有任何級別的 TCP API 可以告訴您 TCP 連接的當(dāng)前狀態(tài),在任何級別上都沒有硅。你必須嘗試使用它。
如果您要發(fā)送 keepalive 探測,服務(wù)器別無選擇,只能做出適當(dāng)?shù)捻憫?yīng)。服務(wù)器甚至不知道它們是?;畹?。他們不是。它們只是重復(fù)的 ACK。支持keepalive就是支持發(fā)送keepalive。
- 2 回答
- 0 關(guān)注
- 1137 瀏覽
添加回答
舉報(bào)