網絡請求的超時原因



網絡的抽象表示

操作系統中,所有網絡請求的建立和數據傳輸,在軟件層面是使用socket(一般翻譯為套接字)來表示,可以把它理解為搭建在網絡請求的客戶端和服務端之間的一個管道,socket的建立類比管道的搭建,數據的傳輸類比管道內水的流動。
套接字是基於TCP/IP實現的,它是TCP的接口在編程語言內的抽象,比如在Java語言中就有對應的ServerSocketSocket類,直接使用編程語言抽象的Socket API即可使用TCP服務。

套接字概述

以Java語言的套接字編程為例,網絡中的數據被網卡接收,網卡把接收到的數據放到自己的接收隊列(ReceiveQueue)中,用戶態執行的代碼沒有辦法直接獲取網卡的數據,需要通過調用操作系統函數讓內核層的代碼獲取網卡隊列的數據,然后再交由用戶編寫的代碼處理。
同樣的,用戶編寫的代碼需要向網絡中發送數據時,需要通過調用操作系統函數把數據交由內核,然后由內核代碼將數據發送至網卡,網卡把待發送的數據放在發送隊列(SendQueue)中,等隊列滿或者內核主動觸發發送的指令,再把隊列中的數據發送至網絡。

上述內容中接收隊列(ReceiveQueue)和發送隊列(SendQueue)稱為操作系統的網絡緩沖區。編程語言的Socket API主要就是抽象了網卡和內核的邏輯部分,讓應用開發人員使用時不必考慮太多細節。例如可以直接通過SocketsetSendBufferSize(int):void控制某個連接的緩沖區大小,也可以直接調用Writerflush():void讓網卡把緩沖區的數據發送至網絡。

超時

連接超時

使用Socket編程或者HTTP編程,在建立連接的時候,經常會遇到連接超時(connect timeout)。一般服務端宕機、網絡不可達等原因會造成這樣的失敗。在Scoket中,默認connect(SocketAddress):void連接方式,連接失敗時會有異常java.net.ConnectException: Connection timed out: connect。使用帶有連接超時參數的連接方式connect(SocketAddress, int):void,在超時時間內未連接成功會拋出異常。

等待超時(Socket讀超時)

接收隊列ReceiveQueue中用來存放從網絡中接收的數據,若是ReceiveQueue沒有數據,接收端會一直阻塞,直到有新的數據到來或者異常發生。若是對端機器宕機或者網絡斷開,接收端的線程仍在阻塞,就會導致連接不能正常關閉。
通過setSoTimeout(int):void設置等待時間,若是在指定時間內ReceiveQueue沒有數據產生,就會有SocketTimeoutException異常,此時Socket連接仍是有效的,為保證資源的釋放,需要在異常發生時關閉連接。

發送超時(Socket寫超時)

Socket的寫超時是基於TCP的超時重傳。超時重傳是TCP保證數據可靠性傳輸的一個重要機制,其原理是在發送一個數據報文后就開啟一個計時器,在一定時間內如果沒有得到發送報文的確認ACK,那么就重新發送報文。如果重新發送多次之后,仍沒有確認報文,就發送一個復位報文RST,然后關閉TCP連接。首次數據報文發送與復位報文傳輸之間的時間差大約為9分鍾,也就是說如果9分鍾內沒有得到確認報文,就關閉連接。但是這個值是根據不同的TCP協議棧實現而不同。

如果發送端持續地寫出數據,直到SendQueue被填滿。如果在SendQueue已滿時仍發送數據,則write():void將被阻塞,直到SendQueue有新的空閑空間為止,也就是說直到一些字節傳輸到了接收者套接字的ReceiveQueue中。如果此時ReceiveQueue隊列也已經被填滿,所有操作都將停止,直到接收端將一些字節傳輸到應用程序。

當Socket的write():void發送數據時,如果網線斷開、對端機器宕機等,TCP模塊會重傳數據,最后超時而關閉連接。下次如再調用write():void會導致一個異常而退出。

Socket寫超時是基於TCP協議棧的超時重傳機制,一般不需要設置發送超時時間,也沒有提供這種方法。

而在OKHttp3中提供了基於HTTP的writeTimeout(long, TimeUnit)設置,OKHttp3提供的writeTimeout(long, TimeUnit)並不是設置數據發送到對端的超時時間,而是指在等待發送數據的過程中,可能由於數據一直被加鎖導致當前程序無法讀取,導致應用層的write()方法阻塞到指定時間而失敗。


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM