




版權(quán)說明:本文檔由用戶提供并上傳,收益歸屬內(nèi)容提供方,若內(nèi)容存在侵權(quán),請進行舉報或認領(lǐng)
文檔簡介
1、 JAVA Socket超時淺析 套接字或插座(socket)是一種軟件形式的抽象,用于表達兩臺機器間一個連接的“終端”。針對一個特定的連接,每臺機器上都有一個“套接字”,可以想象它們之間有一條虛擬的“線纜”。JAVA有兩個基于數(shù)據(jù)流的套接字類:ServerSocket,服務(wù)器用它“偵聽”進入的連接;Socket,客戶端用它初始一次連接。偵聽套接字只能接收新的連接請求,不能接收實際的數(shù)據(jù)包。 套接字是基于TCP/IP實現(xiàn)的,它是用來提供一個訪問TCP的服務(wù)接口,或者說套接字socket是TCP的應(yīng)用編程接口API,通過它應(yīng)用層就可以訪問TCP提供的服務(wù)。在JA
2、VA中,我們用ServerSocket、Socket類創(chuàng)建一個套接字連接,從套接字得到的結(jié)果是一個InputStream以及OutputStream對象,以便將連接作為一個IO流對象對待。通過IO流可以從流中讀取數(shù)據(jù)或者寫數(shù)據(jù)到流中,讀寫IO流會有異常IOException產(chǎn)生。 套接字底層是基于TCP的,所以socket的超時和TCP超時是相同的。下面先討論套接字讀寫緩沖區(qū),接著討論連接建立超時、讀寫超時以及JAVA套接字編程的嵌套異常捕獲和一個超時例子程序的抓包示例。 1 socket讀寫緩沖區(qū) 一旦創(chuàng)建了一個套接字實例,操作系統(tǒng)就會為其分配緩沖區(qū)以存放接
3、收和要發(fā)送的數(shù)據(jù)。 JAVA可以設(shè)置讀寫緩沖區(qū)的大小-setReceiveBufferSize(int size), setSendBufferSize(int size)。 向輸出流寫數(shù)據(jù)并不意味著數(shù)據(jù)實際上已經(jīng)被發(fā)送,它們只是被復(fù)制到了發(fā)送緩沖區(qū)隊列SendQ,就是在Socket的OutputStream上調(diào)用flush()方法,也不能保證數(shù)據(jù)能夠立即發(fā)送到網(wǎng)絡(luò)。真正的數(shù)據(jù)發(fā)送是由操作系統(tǒng)的TCP協(xié)議棧模塊從緩沖區(qū)中取數(shù)據(jù)發(fā)送到網(wǎng)絡(luò)來完成的。 當(dāng)有數(shù)據(jù)從網(wǎng)絡(luò)來到時,TCP協(xié)議棧模塊接收數(shù)據(jù)并放入接收緩沖區(qū)隊列RecvQ,輸入流In
4、putStream通過read方法從RecvQ中取出數(shù)據(jù)。 2 socket連接建立超時 socket連接建立是基于TCP的連接建立過程。TCP的連接需要通過3次握手報文來完成,開始建立TCP連接時需要發(fā)送同步SYN報文,然后等待確認報文SYN+ACK,最后再發(fā)送確認報文ACK。TCP連接的關(guān)閉通過4次揮手來完成,主動關(guān)閉TCP連接的一方發(fā)送FIN報文,等待對方的確認報文;被動關(guān)閉的一方也發(fā)送FIN報文,然等待確認報文。 正在等待TCP連接請求的一端有一個固定長度的連接隊列,該隊列中的連接已經(jīng)被TCP接受(即三次握手已經(jīng)完成),但還沒有被應(yīng)用層所接受。TCP接
5、受一個連接是將其放入這個連接隊列,而應(yīng)用層接受連接是將其從該隊列中移出。應(yīng)用層可以通過設(shè)置backlog變量來指明該連接隊列的最大長度,即已被TCP接受而等待應(yīng)用層接受的最大連接數(shù)。 當(dāng)一個連接請求SYN到達時,TCP確定是否接受這個連接。如果隊列中還有空間,TCP模塊將對SYN進行確認并完成連接的建立。但應(yīng)用層只有在三次握手中的第三個報文收到后才會知道這個新連接。如果隊列沒有空間,TCP將不理會收到的SYN。 如果應(yīng)用層不能及時接受已被TCP接受的連接,這些連接可能占滿整個連接隊列,新的連接請求可能不被響應(yīng)而會超時。如果一個連接請求SYN發(fā)送后,一段時間后沒有收到確認
6、SYN+ACK,TCP會重傳這個連接請求SYN兩次,每次重傳的時間間隔加倍,在規(guī)定的時間內(nèi)仍沒有收到SYN+ACK,TCP將放棄這個連接請求,連接建立就超時了。 JAVA Socket連接建立超時和TCP是相同的,如果TCP建立連接時三次握手超時,那么導(dǎo)致Socket連接建立也就超時了。可以設(shè)置Socket連接建立的超時時間-connect(SocketAddress endpoint, int timeout)如果在timeout內(nèi),連接沒有建立成功,在TimeoutException異常被拋出。如果timeout的值小于三次握手的時間,那么Socket連接永遠也不會建立。
7、60; 不同的應(yīng)用層有不同的連接建立過程,Socket的連接建立和TCP一樣-僅僅需要三次握手就完成連接,但有些應(yīng)用程序需要交互很多信息后才能成功建立連接,比如Telnet協(xié)議,在TCP三次握手完成后,需要進行選項協(xié)商之后,Telnet連接才建立完成。 3 socket讀超時 如果輸入緩沖隊列RecvQ中沒有數(shù)據(jù),read操作會一直阻塞而掛起線程,直到有新的數(shù)據(jù)到來或者有異常產(chǎn)生。調(diào)用setSoTimeout(int timeout)可以設(shè)置超時時間,如果到了超時時間仍沒有數(shù)據(jù),read會拋出一個SocketTimeoutException,程序需要捕獲這個異常,但是當(dāng)前
8、的socket連接仍然是有效的。 如果對方進程崩潰、對方機器突然重啟、網(wǎng)絡(luò)斷開,本端的read會一直阻塞下去,這時設(shè)置超時時間是非常重要的,否則調(diào)用read的線程會一直掛起。 TCP模塊把接收到的數(shù)據(jù)放入RecvQ中,直到應(yīng)用層調(diào)用輸入流的read方法來讀取。如果RecvQ隊列被填滿了,這時TCP會根據(jù)滑動窗口機制通知對方不要繼續(xù)發(fā)送數(shù)據(jù),本端停止接收從對端發(fā)送來的數(shù)據(jù),直到接收者應(yīng)用程序調(diào)用輸入流的read方法后騰出了空間。 4 socket寫超時 socket的寫超時是基于TCP的超時重傳。超時重傳是TCP保證數(shù)據(jù)可靠性傳輸?shù)囊粋€重要機制,其原
9、理是在發(fā)送一個數(shù)據(jù)報文后就開啟一個計時器,在一定時間內(nèi)如果沒有得到發(fā)送報文的確認ACK,那么就重新發(fā)送報文。如果重新發(fā)送多次之后,仍沒有確認報文,就發(fā)送一個復(fù)位報文RST,然后關(guān)閉TCP連接。首次數(shù)據(jù)報文發(fā)送與復(fù)位報文傳輸之間的時間差大約為9分鐘,也就是說如果9分鐘內(nèi)沒有得到確認報文,就關(guān)閉連接。但是這個值是根據(jù)不同的TCP協(xié)議棧實現(xiàn)而不同。 如果發(fā)送端調(diào)用write持續(xù)地寫出數(shù)據(jù),直到SendQ隊列被填滿。如果在SendQ隊列已滿時調(diào)用write方法,則write將被阻塞,直到SendQ有新的空閑空間為止,也就是說直到一些字節(jié)傳輸?shù)搅私邮照咛捉幼值腞ecvQ中。如果此時RecvQ
10、隊列也已經(jīng)被填滿,所有操作都將停止,直到接收端調(diào)用read方法將一些字節(jié)傳輸?shù)綉?yīng)用程序。 當(dāng)Socket的write發(fā)送數(shù)據(jù)時,如果網(wǎng)線斷開、對端進程崩潰或者對端機器重啟動,TCP模塊會重傳數(shù)據(jù),最后超時而關(guān)閉連接。下次如再調(diào)用write會導(dǎo)致一個異常而退出。 Socket寫超時是基于TCP協(xié)議棧的超時重傳機制,一般不需要設(shè)置write的超時時間,也沒有提供這種方法。 5 雙重嵌套異常捕獲 如果ServerSocket、Socket構(gòu)造失敗,只需要僅僅捕獲這個構(gòu)造失敗異常而不需要調(diào)用套接字的close方法來釋放資源(必須保證構(gòu)造失敗后不
11、會留下任何需要清除的資源),因為這時套接字內(nèi)部資源沒有被成功分配。如果構(gòu)造成功,必須進入一個try finally語句塊里調(diào)用close釋放套接字。請參照下面例子程序。java view plaincopy1. import .*; 2. import java.io.*; 3. public class SocketClientTest 4. 5. public static final int PO
12、RT = 8088; 6. public static void main( String args ) throws Exception 7. 8. InetAddress addr = InetAddress.getByName( "127.0.0.1" );&
13、#160; 9. Socket socket = new Socket(); 10. try 11. 12. socket.connect( new InetSocketAddress( addr, PORT ),&
14、#160;30000 ); 13. socket.setSendBufferSize(100); 14. 15. BufferedWriter out = new BufferedWriter( new OutputStreamWriter(
15、160;socket.getOutputStream() ) ); 16. int i = 0; 17. 18. while( true ) 19. &
16、#160; 20. System.out.println( "client sent - hello * " + i+ ); 21. out.write( "client sent - hello *
17、60;" + i ); 22. out.flush(); 23. 24. Thread.sleep( 1000 ); 25.
18、 26. 27. finally 28. 29. socket.close(); 30. 31. 32.
19、0; java view plaincopy1. import java.io.*; 2. import .ServerSocket; 3. import .Socket; 4. public class SocketServerTest 5. 6. public static final int PORT = 8088;
20、0; 7. public static final int BACKLOG = 2; 8. public static void main( String args ) throws IOException 9. 10. ServerSocket se
21、rver = new ServerSocket( PORT, BACKLOG ); 11. System.out.println("started: " + server); 12. try 13. 14.
22、 Socket socket = server.accept(); 15. try 16. 17. BufferedReader in = new BufferedReader( new
23、160;InputStreamReader( socket.getInputStream() ) ); 18. String info = null; 19. 20. while(
24、160;( info = in.readLine() ) != null ) 21. 22. System.out.println( info ); 23.
25、0; 24. 25. finally 26. 27. socket.close(); 28.
26、0; 29. 30. finally 31. 32. server.close(); 33. 34. 35.
27、160; 執(zhí)行上面的程序,在程序運行一會兒之后,斷開client和server之間的網(wǎng)絡(luò)連接,在機器上輸出如下: Server上的輸出:Echoing:client sent -hello0 Echoing:client sent -hello1Echoing:client sent -hello2Echoing:client sent -hello3Echoing:client sent -hello4Echoing:client sent -hello5Echoing:client sent -hello6 ->> 斷開了網(wǎng)絡(luò)連接之后沒
28、有數(shù)據(jù)輸出 Client上的輸出:socket default timeout = 0socket = Socketaddr=/10.15.9.99,port=8088,localport=4691begin to readclient sent - hello * 0client sent - hello * 1client sent - hello * 2client sent - hello * 3client sent - hello * 4client sent - hello * 5client sent - hello * 6client sent - hello *
29、7client sent - hello * 8 client sent - hello * 9client sent - hello * 10 ->> 斷開網(wǎng)絡(luò)連接后客戶端進程掛起 .SocketException : Connection reset by peer: socket write error at .SocketOutputStream.socketWrite0( Native Method ) at .SocketOutputStream.socketWrite( SocketOutputSt
溫馨提示
- 1. 本站所有資源如無特殊說明,都需要本地電腦安裝OFFICE2007和PDF閱讀器。圖紙軟件為CAD,CAXA,PROE,UG,SolidWorks等.壓縮文件請下載最新的WinRAR軟件解壓。
- 2. 本站的文檔不包含任何第三方提供的附件圖紙等,如果需要附件,請聯(lián)系上傳者。文件的所有權(quán)益歸上傳用戶所有。
- 3. 本站RAR壓縮包中若帶圖紙,網(wǎng)頁內(nèi)容里面會有圖紙預(yù)覽,若沒有圖紙預(yù)覽就沒有圖紙。
- 4. 未經(jīng)權(quán)益所有人同意不得將文件中的內(nèi)容挪作商業(yè)或盈利用途。
- 5. 人人文庫網(wǎng)僅提供信息存儲空間,僅對用戶上傳內(nèi)容的表現(xiàn)方式做保護處理,對用戶上傳分享的文檔內(nèi)容本身不做任何修改或編輯,并不能對任何下載內(nèi)容負責(zé)。
- 6. 下載文件中如有侵權(quán)或不適當(dāng)內(nèi)容,請與我們聯(lián)系,我們立即糾正。
- 7. 本站不保證下載資源的準(zhǔn)確性、安全性和完整性, 同時也不承擔(dān)用戶因使用這些下載資源對自己和他人造成任何形式的傷害或損失。
最新文檔
- 變壓器租賃服務(wù)3篇
- 供水合同規(guī)定供水工程合同3篇
- 充電站數(shù)據(jù)分析協(xié)議3篇
- 企業(yè)服務(wù)專業(yè)合同2篇
- 紙制品行業(yè)綠色發(fā)展趨勢考核試卷
- 電力儀表的數(shù)字孿生模型考核試卷
- 膠合板生產(chǎn)場所的應(yīng)急預(yù)案制定考核試卷
- 有色金屬壓延加工企業(yè)品牌建設(shè)考核試卷
- 2025-2026年研究和試驗開展的核心技術(shù)概覽
- 2025汽車購買合同簡單版協(xié)議書
- 水利工程竣工自查報告
- 新疆維吾爾自治區(qū)新2024年中考數(shù)學(xué)模擬試卷附答案
- 2024年中國老年糖尿病診療指南解讀(2024年版)
- 震后學(xué)校維修合同書
- 李白:《將進酒》經(jīng)典省公開課一等獎全國示范課微課金獎?wù)n件
- 19S406建筑排水管道安裝-塑料管道
- 教師如何有效地與家長溝通
- 第11課遼宋夏金元的經(jīng)濟社會與文化教學(xué)設(shè)計-高中歷史必修中外歷史綱要上冊2
- 如何與客戶建立有效的溝通
- 真空排水系統(tǒng)施工方案設(shè)計
- (完整版)建筑工程技術(shù)畢業(yè)論文
評論
0/150
提交評論