2008-10-08 74 views
1

當數據包傳輸永久失敗時,TCP/IP如何報告錯誤?我所見過的所有Socket.write()API只是將字節傳遞到底層TCP/IP輸出緩衝區,並異步傳輸數據。那麼TCP/IP如何通知開發者數據包傳輸是否永久失敗(即目標主機不再可達)?TCP/IP如何報告錯誤?

任何要求發送方等待遠端確認的協議都會收到錯誤消息。但是對於發送者不需要從目的地讀取任何字節的協議會發生什麼? TCP/IP只是默默地失敗了嗎?也許Socket.close()會返回一個錯誤? TCP/IP規範是否對此有任何說明?

回答

5

TCP/IP是一個可靠的字節流協議。你的所有字節都會到達接收器,否則你會得到一個錯誤指示。

錯誤指示將以封閉套接字的形式出現。不管通信模式(誰發送),如果字節無法傳遞,套接字將關閉。

所以問題是,你怎麼看到插座關閉?如果你從來沒有讀過,你最終會試圖寫入封閉的套接字(使用ECONNRESET errno,我想)會出錯。

如果您需要睡眠或等待另一個文件句柄的輸入,您可能希望在select()調用中等待,您可以在其中包含套接字的源代碼列表中如果你從未期望收到任何東西)。如果select()指示套接字已準備好進行讀取調用,那麼您可能會得到-1返回值(使用ECONNRESET,我認爲)。 EOF將指示有序關閉(另一側執行shutdown()或close()。

如何從乾淨的關閉中區分這個錯誤(例如,其他程序正在退出)?errno值可能足以滿足區分錯誤和有序關閉

如果你想明確指出一個問題,你可能需要在套接字層上面建立一些應用層協議。例如,一個簡短的「ack」接收者返回給發送者,然後違反該更高級別的應用協議(發送者沒有看到ack)將確認這是一個接近乾淨關閉的錯誤。

4

套接字API沒有辦法通知編寫者到底有多少字節已被對方確認。不存在成功的shutdownclose的保證。

TCP/IP規範沒有提到應用程序接口(幾乎總是套接字API)。

SCTP是TCP的替代方案,它試圖解決這些缺點等等。

+0

SCTP看起來很酷!我想知道如何將網絡從TCP/IP遷移到SCTP。聽起來像一個複雜的任務。 – Gili 2008-10-08 16:02:16

0

在C中,如果您寫入發送失敗的套接字(),您將收回發送的字節數。如果這與您要發送的字節數不匹配,那麼您遇到了問題。但是,當你寫入失敗的套接字時,你會收到SIGPIPE。在開始套接字處理之前,您需要有一個信號處理程序,當您獲得SIGPIPE時會提醒您。

如果您正在從套接字中讀取數據,那麼您確實應該使用警報來包裝它,以便您可以超時。像「alarm(timeout_val); recv(); alarm(0)」。檢查recv的返回碼,如果它爲0,則表示連接已關閉。否定的返回結果表示讀取失敗,您需要檢查errno。

+0

send()是一個阻塞函數嗎?在返回發送的字節數之前,它是否真的等待確認?還是純粹傾銷字節輸出緩衝區,並立即返回? – Gili 2008-10-08 15:58:30

0

TCP是基於IP協議,它是互聯網的核心,提供多驅動路由互操作性,這是確定如何從源到目的地獲取數據包的建立。 IP協議指定在數據包未能到達發件人的情況下,應通過Internet控制消息協議(ICMP)將錯誤消息發送回發件人。其中一些原因包括生存時間(TTL)字段減少到零,這通常意味着數據包卡在路由循環中,或者由於交換機爭用導致緩衝區溢出而導致數據包丟失。正如其他人所說,這是正在使用的IP中繼這些錯誤層一直到應用程序與網絡在TCP層交互的的Socket API的責任。