




版權(quán)說明:本文檔由用戶提供并上傳,收益歸屬內(nèi)容提供方,若內(nèi)容存在侵權(quán),請(qǐng)進(jìn)行舉報(bào)或認(rèn)領(lǐng)
文檔簡(jiǎn)介
1、Java網(wǎng)絡(luò)編程精解第3章 ServerSocket用法詳解 參考Java網(wǎng)絡(luò)編程精解的第3章n3.1 構(gòu)造ServerSocketn3.2 接收和關(guān)閉與客戶的連接n3.3 關(guān)閉ServerSocketn3.4 獲取ServerSocket的信息n3.5 ServerSocket選項(xiàng)n3.6 創(chuàng)建多線程的服務(wù)器n3.7 關(guān)閉服務(wù)器3.1 構(gòu)造ServerSocketnServerSocket的構(gòu)造方法有以下幾種重載形式:n(1)ServerSocket()throws IOException n(2)ServerSocket(int port) throws IOException n(3)S
2、erverSocket(int port, int backlog) throws IOExceptionn(4)ServerSocket(int port, int backlog, InetAddress bindAddr) throws IOException 3.1.1 綁定端口ServerSocket serverSocket=new ServerSocket(80);n如果運(yùn)行時(shí)無法綁定到80端口,以上代碼會(huì)拋出IOException,更確切的說,是拋出BindException,它是IOException的子類。nBindException一般是由以下原因造成的:n端口已經(jīng)被其他
3、服務(wù)器進(jìn)程占用。n在某些操作系統(tǒng)中,如果沒有以超級(jí)用戶的身份來運(yùn)行服務(wù)器程序,那么操作系統(tǒng)不允許服務(wù)器綁定到11023之間的端口。3.1.2 設(shè)定客戶連接請(qǐng)求隊(duì)列的長(zhǎng)度 serverSocket = new ServerSocket(port,3); /連接請(qǐng)求隊(duì)列的長(zhǎng)度為3nServerSocket構(gòu)造方法的backlog參數(shù)用來顯式設(shè)置連接請(qǐng)求隊(duì)列的長(zhǎng)度,它將覆蓋操作系統(tǒng)限定的隊(duì)列的最大長(zhǎng)度。n值得注意的是,在以下幾種情況,仍然會(huì)采用操作系統(tǒng)限定的隊(duì)列的最大長(zhǎng)度:nbacklog參數(shù)的值大于操作系統(tǒng)限定的隊(duì)列的最大長(zhǎng)度。nbacklog參數(shù)的值小于或等于0。n在ServerSocket構(gòu)造
4、方法中沒有設(shè)置backlog參數(shù)。3.1.3 設(shè)定綁定的IP地址nserverSocket=new ServerSocket(8000,10,InetAddress.getByName();n如果主機(jī)只有一個(gè)IP地址,那么默認(rèn)情況下,服務(wù)器程序就與該IP地址綁定。nServerSocket的第四個(gè)構(gòu)造方法ServerSocket(int port, int backlog, InetAddress bindAddr)有一個(gè)bindAddr參數(shù),它顯式指定服務(wù)器要綁定的IP地址,該構(gòu)造方法適用于具有多個(gè)IP地址的主機(jī)。3.1.4 默認(rèn)構(gòu)造方法的作用n通過該方法創(chuàng)建的Serv
5、erSocket不與任何端口綁定,接下來還需要通過bind()方法與特定端口綁定。n在以下代碼中,先把ServerSocket的SO_REUSEADDR選項(xiàng)設(shè)為true,然后再把它與8000端口綁定:ServerSocket serverSocket=new ServerSocket();serverSocket.setReuseAddress(true); /設(shè)置ServerSocket的選項(xiàng)serverSocket.bind(new InetSocketAddress(8000); /與8000端口綁定3.2 接收和關(guān)閉與客戶的連接public void service() /單線程服務(wù)器
6、采用的通信流程 while (true) Socket socket=null; try socket = serverSocket.accept(); /從連接請(qǐng)求隊(duì)列中取出一個(gè)連接 System.out.println(New connection accepted + socket.getInetAddress() + : +socket.getPort(); /接收和發(fā)送數(shù)據(jù) catch (IOException e) /這只是與單個(gè)客戶通信時(shí)遇到的異常,可能是由于客戶端過早斷開連接引起的 /這種異常不應(yīng)該中斷整個(gè)while循環(huán) e.printStackTrace(); finally
7、 try if(socket!=null)socket.close(); /與一個(gè)客戶通信結(jié)束后,要關(guān)閉Socket catch (IOException e) e.printStackTrace(); 3.3 關(guān)閉ServerSocketn以下程序代碼創(chuàng)建了一個(gè)ServerSocket對(duì)象后,就馬上關(guān)閉它,以便及時(shí)釋放它占用的端口,從而避免程序臨時(shí)占用系統(tǒng)的大多數(shù)端口。for(int port=1;port=65535;port+) try ServerSocket serverSocket=new ServerSocket(port); serverSocket.close(); /及時(shí)關(guān)
8、閉ServerSocket catch(IOException e) System.out.println(端口+port+ 已經(jīng)被其他服務(wù)器進(jìn)程占用); 3.4 獲取ServerSocket的信息nServerSocket的以下兩個(gè)get方法分別獲得服務(wù)器綁定的IP地址,以及綁定的端口:npublic InetAddress getInetAddress()npublic int getLocalPort()3.5 ServerSocket選項(xiàng)nSO_TIMEOUT:表示等待客戶連接的超時(shí)時(shí)間。nSO_REUSEADDR:表示是否允許重用服務(wù)器所綁定的地址。nSO_RCVBUF:表示接收數(shù)據(jù)
9、的緩沖區(qū)的大小。3.5.1 SO_TIMEOUT選項(xiàng)n設(shè)置該選項(xiàng):public void setSoTimeout(int timeout) throws SocketExceptionn讀取該選項(xiàng):public int getSoTimeout () throws IOExceptionnSO_TIMEOUT表示ServerSocket的accept()方法等待客戶連接的超時(shí)時(shí)間,以毫秒為單位。如果SO_TIMEOUT的值為0,表示永遠(yuǎn)不會(huì)超時(shí),這是SO_TIMEOUT的默認(rèn)值。n當(dāng)服務(wù)器執(zhí)行ServerSocket的accept()方法時(shí),如果連接請(qǐng)求隊(duì)列為空,服務(wù)器就會(huì)一直等待,直到接收
10、到了客戶連接才從accept()方法返回。如果設(shè)定了超時(shí)時(shí)間,那么當(dāng)服務(wù)器等待的時(shí)間超過了超時(shí)時(shí)間,就會(huì)拋出SocketTimeoutException,它是InterruptedException的子類。3.5.2 SO_REUSEADDR選項(xiàng)n設(shè)置該選項(xiàng):public void setResuseAddress(boolean on) throws SocketExceptionn讀取該選項(xiàng):public boolean getResuseAddress() throws SocketExceptionn這個(gè)選項(xiàng)與Socket的SO_REUSEADDR選項(xiàng)相同,用于決定如果網(wǎng)絡(luò)上仍然有數(shù)據(jù)
11、向舊的ServerSocket傳輸,是否允許新的ServerSocket綁定到與舊的ServerSocket同樣的端口。n為了確保一個(gè)進(jìn)程關(guān)閉了ServerSocket后,即使操作系統(tǒng)還沒釋放端口,同一個(gè)主機(jī)上的其他進(jìn)程還可以立刻重用該端口,可以調(diào)用ServerSocket的setResuseAddress(true)方法。n值得注意的是,serverSocket.setResuseAddress(true)方法必須在ServerSocket還沒有綁定到一個(gè)本地端口之前調(diào)用,否則執(zhí)行serverSocket.setResuseAddress(true)方法無效。 3.5.3 SO_RCVBUF
12、選項(xiàng)n設(shè)置該選項(xiàng):public void setReceiveBufferSize(int size) throws SocketExceptionn讀取該選項(xiàng):public int getReceiveBufferSize() throws SocketExceptionnSO_RCVBUF表示服務(wù)器端的用于接收數(shù)據(jù)的緩沖區(qū)的大小,以字節(jié)為單位。一般說來,傳輸大的連續(xù)的數(shù)據(jù)塊(比如基于HTTP或FTP協(xié)議的數(shù)據(jù)傳輸)可以使用較大的緩沖區(qū),這可以減少傳輸數(shù)據(jù)的次數(shù),從而提高傳輸數(shù)據(jù)的效率。而對(duì)于交互式的通信(比如Telnet和網(wǎng)絡(luò)游戲),則應(yīng)該采用小的緩沖區(qū),確保能及時(shí)把小批量的數(shù)據(jù)發(fā)送給對(duì)方
13、。n執(zhí)行serverSocket.setReceiveBufferSize()方法,相當(dāng)于對(duì)所有由serverSocket.accept()方法返回的Socket設(shè)置接收數(shù)據(jù)的緩沖區(qū)的大小。3.5.4 設(shè)定連接時(shí)間、延遲和帶寬的相對(duì)重要性npublic void setPerformancePreferences(int connectionTime,int latency,int bandwidth)n該方法的作用與Socket的setPerformancePreferences()方法的作用相同,用于設(shè)定連接時(shí)間、延遲和帶寬的相對(duì)重要性。3.6 創(chuàng)建多線程的服務(wù)器n可以用并發(fā)性能來衡量一個(gè)
14、服務(wù)器同時(shí)響應(yīng)多個(gè)客戶的能力。一個(gè)具有好的并發(fā)性能的服務(wù)器,必須符合兩個(gè)條件:n能同時(shí)接收并處理多個(gè)客戶連接。n對(duì)于每個(gè)客戶,都會(huì)迅速給予響應(yīng)。n服務(wù)器同時(shí)處理的客戶連接數(shù)目越多,并且對(duì)每個(gè)客戶做出響應(yīng)的速度越快,就表明并發(fā)性能越高。3.6 創(chuàng)建多線程的服務(wù)器n用多個(gè)線程來同時(shí)為多個(gè)客戶提供服務(wù),這是提高服務(wù)器的并發(fā)性能的最常用的手段。本節(jié)將按照三種方式來重新實(shí)現(xiàn)EchoServer,它們都使用了多線程:n方式一:為每個(gè)客戶分配一個(gè)工作線程。n方式二:創(chuàng)建一個(gè)線程池,由其中的工作線程來為客戶服務(wù)。n方式三:利用JDK的Java類庫(kù)中現(xiàn)成的線程池,由它的工作線程來為客戶服務(wù)。3.6.1 為每個(gè)客
15、戶分配一個(gè)線程n服務(wù)器的主線程負(fù)責(zé)接收客戶的連接,每次接收到一個(gè)客戶連接,就會(huì)創(chuàng)建一個(gè)工作線程,由它負(fù)責(zé)與客戶的通信。以下是EchoServer的service()方法的代碼:public void service() while (true) Socket socket=null; try socket = serverSocket.accept(); /接收客戶連接 Thread workThread=new Thread(new Handler(socket); /創(chuàng)建一個(gè)工作線程 workThread.start(); /啟動(dòng)工作線程 catch (IOException e) e.p
16、rintStackTrace(); 3.6.2 創(chuàng)建線程池n線程池為線程生命周期開銷問題和系統(tǒng)資源不足問題提供了解決方案。線程池中預(yù)先創(chuàng)建了一些工作線程,它們不斷從工作隊(duì)列中取出任務(wù),然后執(zhí)行該任務(wù)。當(dāng)工作線程執(zhí)行完一個(gè)任務(wù),就會(huì)繼續(xù)執(zhí)行工作隊(duì)列中的下一個(gè)任務(wù)。n線程池具有以下優(yōu)點(diǎn):n減少了創(chuàng)建和銷毀線程的次數(shù),每個(gè)工作線程都可以一直被重用,能執(zhí)行多個(gè)任務(wù)。n可以根據(jù)系統(tǒng)的承載能力,方便的調(diào)整線程池中線程的數(shù)目,防止因?yàn)橄倪^量系統(tǒng)資源而導(dǎo)致系統(tǒng)崩潰。n參見ThreadPool類3.6.3 使用JDK類庫(kù)提供的線程池njava.util.concurrent包提供了現(xiàn)成的線程池的實(shí)現(xiàn)。Exec
17、utor接口表示線程池,它的execute(Runnable task)方法用來執(zhí)行Runnable類型的任務(wù)。Executor的子接口ExecutorService中聲明了管理線程池的一些方法,比如用于關(guān)閉線程池的shutdown()方法等。Executors類中包含一些靜態(tài)方法,它們負(fù)責(zé)生成各種類型的線程池ExecutorService實(shí)例。3.6.3 使用JDK類庫(kù)提供的線程池3.6.3 使用JDK類庫(kù)提供的線程池nEchoServer就利用上述線程池來負(fù)責(zé)與客戶通信的任務(wù)。 public EchoServer() throws IOException serverSocket = ne
18、w ServerSocket(port); /創(chuàng)建線程池 /Runtime的availableProcessors()方法返回當(dāng)前系統(tǒng)的CPU的數(shù)目 /系統(tǒng)的CPU越多,線程池中工作線程的數(shù)目也越多 executorService= Executors.newFixedThreadPool( Runtime.getRuntime().availableProcessors() * POOL_SIZE); System.out.println(服務(wù)器啟動(dòng)); 3.6.4 使用線程池的注意事項(xiàng)n線程池可能會(huì)帶來種種風(fēng)險(xiǎn):n1死鎖n2系統(tǒng)資源不足n3并發(fā)錯(cuò)誤n4線程泄漏n5任務(wù)過載3.6.4 使用線程池的注意事項(xiàng)n使用線程池時(shí)需要遵循以下原則:n(1)如果任務(wù)A在執(zhí)行過程中需要同步等待任務(wù)B的執(zhí)行結(jié)果,那么任務(wù)A不適合加入到線程池的工作隊(duì)列中。n(2)如果執(zhí)行某個(gè)任務(wù)時(shí)可能會(huì)阻塞,并且是長(zhǎng)時(shí)間的阻塞,則應(yīng)該設(shè)定超時(shí)時(shí)間,避免工作線程永久的阻塞下去而導(dǎo)致線程泄漏。n(3)根據(jù)任務(wù)的特點(diǎn),對(duì)任務(wù)進(jìn)行分類,然后把不同類型的任務(wù)分別加入到不同線程池的工作隊(duì)列中,這樣可以根據(jù)任務(wù)的特點(diǎn),分別調(diào)整每個(gè)線程池。n(4)調(diào)整
溫馨提示
- 1. 本站所有資源如無特殊說明,都需要本地電腦安裝OFFICE2007和PDF閱讀器。圖紙軟件為CAD,CAXA,PROE,UG,SolidWorks等.壓縮文件請(qǐng)下載最新的WinRAR軟件解壓。
- 2. 本站的文檔不包含任何第三方提供的附件圖紙等,如果需要附件,請(qǐng)聯(lián)系上傳者。文件的所有權(quán)益歸上傳用戶所有。
- 3. 本站RAR壓縮包中若帶圖紙,網(wǎng)頁(yè)內(nèi)容里面會(huì)有圖紙預(yù)覽,若沒有圖紙預(yù)覽就沒有圖紙。
- 4. 未經(jīng)權(quán)益所有人同意不得將文件中的內(nèi)容挪作商業(yè)或盈利用途。
- 5. 人人文庫(kù)網(wǎng)僅提供信息存儲(chǔ)空間,僅對(duì)用戶上傳內(nèi)容的表現(xiàn)方式做保護(hù)處理,對(duì)用戶上傳分享的文檔內(nèi)容本身不做任何修改或編輯,并不能對(duì)任何下載內(nèi)容負(fù)責(zé)。
- 6. 下載文件中如有侵權(quán)或不適當(dāng)內(nèi)容,請(qǐng)與我們聯(lián)系,我們立即糾正。
- 7. 本站不保證下載資源的準(zhǔn)確性、安全性和完整性, 同時(shí)也不承擔(dān)用戶因使用這些下載資源對(duì)自己和他人造成任何形式的傷害或損失。
最新文檔
- 山里踏雪活動(dòng)方案
- 展廳寵物活動(dòng)方案
- 小紅帽公司活動(dòng)策劃方案
- 山西省基礎(chǔ)教育活動(dòng)方案
- 布丁酒店活動(dòng)方案
- 工作迎新活動(dòng)方案
- 小學(xué)生居家游戲活動(dòng)方案
- 小柴米充值活動(dòng)方案
- 盡快落實(shí)活動(dòng)方案
- 師生環(huán)保進(jìn)社區(qū)活動(dòng)方案
- GB/T 31848-2015汽車貼膜玻璃貼膜要求
- 圖書管理系統(tǒng)畢業(yè)論文參考文獻(xiàn)精選,參考文獻(xiàn)
- 行政法培訓(xùn)講義課件
- 中國(guó)當(dāng)代舊體詩(shī)選讀幻燈片
- 吉林省全省市縣鄉(xiāng)鎮(zhèn)衛(wèi)生院街道社區(qū)衛(wèi)生服務(wù)中心基本公共衛(wèi)生服務(wù)醫(yī)療機(jī)構(gòu)信息名單目錄995家
- 倔強(qiáng)的小紅軍-精講版課件
- 信息隱藏與數(shù)字水印課件(全)全書教學(xué)教程完整版電子教案最全幻燈片
- 公開招聘社區(qū)居委專職工作人員考試筆試、面試題集及相關(guān)知識(shí)(11套試題含答案)
- 三相負(fù)荷(380V)及單相(220V)最大供電距離計(jì)算表及電壓降計(jì)算表
- 中職數(shù)學(xué)基礎(chǔ)模塊下冊(cè)《等差數(shù)列》ppt說課稿
- 計(jì)算機(jī)網(wǎng)絡(luò)專業(yè)畢業(yè)論文:網(wǎng)上鮮花銷售系統(tǒng)的設(shè)計(jì)與實(shí)現(xiàn)
評(píng)論
0/150
提交評(píng)論