版權(quán)說明:本文檔由用戶提供并上傳,收益歸屬內(nèi)容提供方,若內(nèi)容存在侵權(quán),請進行舉報或認領(lǐng)
文檔簡介
1、第十三章 Java網(wǎng)絡編程一、Java套接字實現(xiàn)網(wǎng)絡編程之基礎(chǔ)篇 1用 Java 開發(fā)網(wǎng)絡軟件非常方便和強大,Java 的這種力量來源于他獨有的一套強大的用于 網(wǎng)絡的 API,這些 API 是一系列的類和接口,均位于包 和 中。在這篇文 章中我們將介紹套接字(Socket)慨念,同時以實例說明如何使 用 Network API 操縱套接字, 在完成本文后,你將具備編寫網(wǎng)絡低端通訊軟件的能力。1、什么是套接字(Socket)?Network API 是典型的用于基于 TCP/IP 網(wǎng)絡 Java 程序與其他程序通訊,Network API 依靠 Socket
2、 進行通訊。Socket 可以看成在兩個程序進行通訊連接中的一個端點,一個程序?qū)?一段信息寫入 Socket 中,該 Socket 將這段信息發(fā)送給另外一個 Socket 中,使這段信息能傳 送到其他程序中。如圖 1我們來分析一下圖 1,Host A 上的程序 A 將一段信息寫入 Socket 中,Socket 的內(nèi)容被 Host A 的網(wǎng)絡管理軟件訪問,并將這段信息通 過 Host A 的網(wǎng)絡接口卡發(fā)送到 Host B,Host B 的網(wǎng)絡接口卡接收到這段信息后,傳送給 Host B 的網(wǎng)絡管理軟件,網(wǎng)絡管理軟件將這段信息 保 存在 Host B 的 Socket 中,然后程序 B 才能在
3、Socket 中閱讀這段信息。假設(shè)在圖 1 的網(wǎng)絡中添加第三個主機 Host C,那么 Host A 怎么知道信息被正確傳送到Host B 而不是被傳送到 Host C 中了呢?基于 TCP/IP 網(wǎng)絡中的每一個主機均被賦予了一個唯 一的 IP 地址,IP 地址是一個 32 位的無符號整數(shù),由于沒有轉(zhuǎn)變成二進制,因此通常以小數(shù)點分隔,如:,正如所見 IP 地址均由四個部分組成,每個部分的范圍都是 0-255, 以表示 8 位地址。值得注意的是 IP 地址都是 32 位地址,這是 IP 協(xié)議版本 4(簡稱 Ipv4)規(guī)定的,目前由于 IPv4 地址已近耗盡,所以 IPv
4、6 地址正逐漸代替 Ipv4 地址,Ipv6 地址則是 128 位無符號 整數(shù)。假設(shè)第二個程序被加入圖 1 的網(wǎng)絡的 Host B 中,那么由 Host A 傳來的信息如何能被正確 的傳給程序 B 而不是傳給新加入的程序呢?這是因為每一個基于 TCP/IP 網(wǎng)絡通訊的程序都被 賦予了唯一的端口和端口號,端口是一個信息緩沖區(qū),用于保留 Socket 中的輸入/輸出信息, 端口號是一個 16 位無符號整數(shù),范圍是 0-65535,以區(qū)別主機上的每一個程序(端口號就像 房屋中的房間號),低于 256 的短口號保留給標準應用程序,比如 pop3 的端口號就是 110, 每一個套接字都組合進了 IP 地
5、址、端口、端口號,這樣形成的整體就可以區(qū)別每一個套接字 t, 下面我們就來談談兩種套接字:流套接字和自尋址數(shù)據(jù)套接字。2、流套接字(Stream Socket) 無論何時,在兩個網(wǎng)絡應用程序之間發(fā)送和接收信息時都需要建立一個可靠的連接,流套接字依靠 TCP 協(xié)議來保證信息正確到達目的地,實際上,IP 包有可能在網(wǎng)絡中丟失或者在傳送過程中發(fā)生錯誤,任何一種情況發(fā)生,作為接受方的 TCP 將聯(lián)系發(fā)送方 TCP 重新發(fā)送這個 IP包。這就是所謂的在兩個流套接字之間建立可靠的連接。流套接字在 C/S 程序中扮演一個必需的角色,客戶機程序(需要訪問某些服務的網(wǎng)絡應用 程序)創(chuàng)建一個扮演服務器程序的主機的
6、 IP 地址和服務器程序(為客戶端應用程序提供服務的 網(wǎng)絡應用程序)的端口號的流套接字對象??蛻舳肆魈捉幼值某跏蓟a將 IP 地址和端口號傳遞給客戶端主機的網(wǎng)絡管理軟件,管理 軟件將 IP 地址和端口號通過 NIC 傳遞給服務器端主機;服務器端主機讀到經(jīng)過 NIC 傳遞來的 數(shù)據(jù),然后查看服務器程序是否處于監(jiān)聽狀態(tài),這種監(jiān)聽依然是通過套接字和端口來進行的;如 果服務器程序處于監(jiān)聽狀態(tài),那么服務器端網(wǎng)絡管理軟件就向客戶機網(wǎng)絡管理軟件發(fā)出一個積極 的響應信號,接收到響應信號后,客戶端流套接字初始化代碼就給客戶程序建立一個端口號,并 將這個端口號傳遞給服務器程序的套接字(服務器程序?qū)⑹褂眠@個端口號
7、識別傳來的信息是否是 屬于客戶程序)同時完成流套接字的初始化。如果服務器程序沒有處于監(jiān)聽狀態(tài),那么服務器端網(wǎng)絡管理軟件將給客戶端傳遞一個消極 信號,收到這個消極信號后,客戶程序的流套接字初始化代碼將拋出一個異常對象并且不建立通 訊連接,也不創(chuàng)建流套接字對象。這種情形就像打電話一樣,當有人的時候通訊建立,否則電話 將被掛起。這部分的工作包括了相關(guān)聯(lián)的三個類:InetAddress, Socket, 和 ServerSocket。 InetAddress 對象描繪了 32 位或 128 位 IP 地 址,Socket 對象代表了客戶程序流套接字,ServerSocket 代表了服務程序流套接字,所
8、有這 三個類均位于包 中。3、InetAddress 類InetAddress 類在網(wǎng)絡 API 套接字編程中扮演了一個重要角色。參數(shù)傳遞給流套接字類和 自尋址套接字類構(gòu)造器或非構(gòu)造器方法。 InetAddress 描述了 32 位或 64 位 IP 地址,要完成 這個功能,InetAddress 類主要依靠兩個支持類 Inet4Address 和 Inet6Address,這三個 類是繼承關(guān)系,InetAddrress 是父類,Inet4Address 和 Inet6Address 是子類。2由于 InetAddress 類只有一個構(gòu)造函數(shù),而且不能傳遞參數(shù),所以不能直接創(chuàng)
9、建InetAddress 對象,比如下面的做法就是錯誤的:InetAddress ia = new InetAddress ();但我們可以通過下面的 5 個工廠方法創(chuàng)建來創(chuàng)建一個 InetAddress 對象或 InetAddress 數(shù)組:. getAllByName(String host)方法返回一個 InetAddress 對象的引用,每個對象包含一個 表示相應主機名的單獨的 IP 地址,這個 IP 地址是通過 host 參數(shù)傳遞的,對于指定的主機如果 沒有 IP 地址存在那么這個方法將拋出一個 UnknownHostException 異常對象。. getByAddress(byt
10、e addr)方法返回一個 InetAddress 對象的引用,這個對象包含了 一個 Ipv4 地址或 Ipv6 地址,Ipv4 地址是一個 4 字節(jié)數(shù)組,Ipv6 地址是一個 16 字節(jié)地址數(shù) 組,如果返回的數(shù)組既不是 4 字節(jié)的也不是 16 字節(jié)的,那么方法將會拋出一個 UnknownHostException 異常對象。. getByAddress(String host, byte addr)方法返回一個 InetAddress 對象的引用,這個 InetAddress 對象包含了一個由 host 和 4 字節(jié)的 addr 數(shù)組指定的 IP 地址,或者是 host和 16 字節(jié)的 ad
11、dr 數(shù)組指定的 IP 地址,如果這 個數(shù)組既不是 4 字節(jié)的也不是 16 位字節(jié)的, 那么該方法將拋出一個 UnknownHostException 異常對象。. getByName(String host)方法返回一個 InetAddress 對象,該對象包含了一個與 host參數(shù)指定的主機相對應的 IP 地址,對于指定的主機如果沒有 IP 地址存在,那么方法將拋出一個 UnknownHostException 異常對象。. getLocalHost()方法返回一個 InetAddress 對象,這個對象包含了本地機的 IP 地址,考 慮到本地主機既是客戶程序主機又是服務器程序主機,為避免
12、混亂,我們將客戶程序主機稱為客 戶主機,將服務器程序主機稱為服務器主機。上面講到的方法均提到返回一個或多個 InetAddress 對象的引用,實際上每一個方法都要 返回一個或多個 Inet4Address/Inet6Address 對象的引用,調(diào)用者不需要知道引用的子類型, 相反調(diào)用者可以使用返回的引用調(diào)用 InetAddress 對象的非靜態(tài)方法,包括子類型的多態(tài)以確 保重載方法被調(diào)用。InetAddress 和它的子類型對象處理主機名到主機 IPv4 或 IPv6 地址的轉(zhuǎn)換,要完成這個 轉(zhuǎn)換需要使用域名系統(tǒng),下面的代碼示范了如何通過調(diào)用 getByName(String host)方法
13、獲得 InetAddress 子類對象的方法,這個對象包含了與 host 參數(shù)相對應的 IP 地址:InetAddress ia = InetAddress.getByName ();一但獲得了 InetAddress 子類對象的引用就可以調(diào)用 InetAddress 的各種方法來獲得InetAddress 子類對象中的 IP 地址信 息,比如,可以通過調(diào)用 getCanonicalHostName() 從域名服務中獲得標準的主機名;getHostAddress()獲得 IP 地址, getHostName()獲得主 機名,isLoopbackAddress()
14、判斷 IP 地址是否是一個 loopback 地址。List1 是一段示范代碼:InetAddressDemo3/ InetAddressDemo.javaimport .*;class InetAddressDemopublic static void main (String args) throws UnknownHostExceptionString host = localhost;if (args.length = 1)host = args 0;InetAddress ia = InetAddress.getByName (host);System.out.pri
15、ntln (Canonical Host Name = +ia.getCanonicalHostName();System.out.println (Host Address = +ia.getHostAddress ();System.out.println (Host Name = +ia.getHostName ();System.out.println (Is Loopback Address = +ia.isLoopbackAddress ();當無命令行參數(shù)時,代碼輸出類似下面的結(jié)果:Canonical Host Name = localhostHost Address = 127
16、.0.0.1Host Name = localhostIs Loopback Address = trueInetAddressDemo 給了你一個指定主機名作為命令行參數(shù)的選擇,如果沒有主機名被指定,那么將使用 localhost(客戶機的), InetAddressDemo 通過調(diào)用 getByName(String host) 方法獲得一個 InetAddress 子類對象的引用,通過這個引用 獲得了標準主機名,主機地址, 主機名以及 IP 地址是否是 loopback 地址的輸出。4、Socket 類當客戶程序需要與服務器程序通訊的時候,客戶程序在客戶機創(chuàng)建一個 socket 對象,S
17、ocket 類有幾個構(gòu)造函數(shù)。兩個常用的構(gòu)造函數(shù)是 Socket(InetAddress addr, int port) 和 Socket(String host, int port),兩個構(gòu)造函數(shù) 都創(chuàng)建了一個基于 Socket 的連接服務器端流套接字的流套接字。對于第一個 InetAddress 子 類對象通過 addr 參數(shù)獲得服務器主機的 IP 地址,對于第二個函數(shù) host 參數(shù)包被分配到 InetAddress 對象中,如果沒有 IP 地址與 host 參數(shù)相一致,那么將拋出 UnknownHostException 異常對象。兩個函數(shù)都通過參數(shù) port 獲得服務器的端口號。假設(shè)
18、已 經(jīng)建立連接了,網(wǎng)絡 API 將在客戶端基于 Socket 的流套接字中捆綁客戶程序的 IP 地址和任意 一個端口號,否則兩個函數(shù)都會拋出一個 IOException 對象。4如果創(chuàng)建了一個 Socket 對象,那么它可能通過調(diào)用 Socket 的 getInputStream()方法 從服務程序獲得輸入流讀傳送來的信息,也可能通過調(diào)用 Socket 的 getOutputStream()方法 獲得輸出流來發(fā)送消息。在讀寫活動完成之后,客戶程序調(diào)用 close()方法關(guān)閉流和流套接字, 下面的代碼創(chuàng)建了一個服務程序主機地址為 ,端口號為 13 的 Socket 對象
19、, 然后從這個新創(chuàng)建的 Socket 對象中讀取輸入流,然后再關(guān)閉流和 Socket 對象。Socket s = new Socket (, 13);InputStream is = s.getInputStream ();/ Read from the stream.is.close ();s.close ();接下面我們將示范一個流套接字的客戶程序,這個程序?qū)?chuàng)建一個 Socket 對象,Socket將訪問運行在指定主機端口 10000 上的服務程序,如果訪問成功客戶程序?qū)⒔o服務程序發(fā)送一 系列命令并打印服務程序的響應。List2 是我們創(chuàng)建的程序 SSClien
20、t 的源代碼:Listing 2: SSClient.java/ SSClient.javaimport java.io.*;import .*;class SSClientpublic static void main (String args)String host = localhost;/ If user specifies a command-line argument, that argument/ represents the host name.if (args.length = 1)host = args 0;BufferedReader br = null;
21、PrintWriter pw = null;Socket s = null;5try/ Create a socket that attempts to connect to the server/ program on the host at port 10000.s = new Socket (host, 10000);/ Create an input stream reader that chains to the sockets/ byte-oriented input stream. The input stream reader/ converts bytes read from
22、 the socket to characters. The/ conversion is based on the platforms default character/ set.InputStreamReader isr;isr = new InputStreamReader (s.getInputStream ();/ Create a buffered reader that chains to the input stream/ reader. The buffered reader supplies a convenient method/ for reading entire
23、lines of text.br = new BufferedReader (isr);/ Create a print writer that chains to the sockets byte-/ oriented output stream. The print writer creates an/ intermediate output stream writer that converts/ characters sent to the socket to bytes. The conversion/ is based on the platforms default charac
24、ter set.pw = new PrintWriter (s.getOutputStream (), true);6/ Send the DATE command to the server.pw.println (DATE);/ Obtain and print the current date/time.System.out.println (br.readLine ();/ Send the PAUSE command to the server. This allows several/ clients to start and verifies that the server is
25、 spawning/ multiple threads.pw.println (PAUSE);/ Send the DOW command to the server.pw.println (DOW);/ Obtain and print the current day of week.System.out.println (br.readLine ();/ Send the DOM command to the server.pw.println (DOM);/ Obtain and print the current day of month.System.out.println (br.
26、readLine ();/ Send the DOY command to the server.pw.println (DOY);/ Obtain and print the current day of year.System.out.println (br.readLine ();7運行這段程序?qū)玫较旅娴慕Y(jié)果:Tue Jan 29 18:11:51 CST 2002TUESDAY2929SSClient 創(chuàng)建了一個 Socket 對象與運行在主機端口 10000 的服務程序聯(lián)系,主機的 IP地址由 host 變量確定。SSClient 將獲得 Socket 的輸入輸出流,圍繞 Buf
27、feredReader 的輸 入流和 PrintWriter 的輸出流對字符串進行讀寫操作就變得非常容易,SSClient 向服務程序發(fā) 出各種 date/time 命令并得到響應,每個響應均被打印,一旦最后一個響應被打印,將執(zhí)行 Try/Catch/Finally 結(jié)構(gòu)的 Finally 子串,F(xiàn)inally 子串將在關(guān)閉 Socket 之前關(guān)閉 BufferedReader 和 PrintWriter。在 SSClient 源代碼編譯完成后,可以輸入 java SSClient 來執(zhí)行這段程序,如果有合適 的程序運行在不同的主機上,采用主機名/IP 地址 為參數(shù)的輸入方式,比如 www.s
28、 是運行服務器程序的主機,那么輸入方式就是 java SSClient 。二、Java套接字實現(xiàn)網(wǎng)絡編程之基礎(chǔ)篇 21、技巧Socket 類包含了許多有用的方法。比如 getLocalAddress()將返回一個包含客戶程序 IP 地址的 InetAddress 子類對象的引用;getLocalPort()將返回客戶程序的端口 號;getInetAddress()將返回一個包含服務器 IP 地址的 InetAddress 子類對象的引用; getPort()將返回服務程序的端口號。2、ServerSocket 類由于 SSClient 使用了流
29、套接字,所以服務程序也要使用流套接字。這就要創(chuàng)建一個 ServerSocket 對象,ServerSocket 有幾個構(gòu)造函數(shù),最簡單的是 ServerSocket(int port), 當使用 ServerSocket (int port)創(chuàng)建一個 ServerSocket 對象,port 參數(shù)傳遞端口號,這個 端口就是服務器監(jiān)聽連接請求的端口,如果在這時出現(xiàn)錯誤將拋出 IOException 異常對象,否 則將創(chuàng)建 ServerSocket 對象并開始準備接收連接請求。接下來服務程序進入無限循環(huán)之中,無限循環(huán)從調(diào)用 ServerSocket 的 accept()方法開始, 在調(diào)用開始后 a
30、ccept()方法將導致調(diào)用線程阻塞直到連接建立。在建立連接后 accept()返回一 個最近創(chuàng)建的 Socket 對象,該 Socket 對象綁定了客戶程序的 IP 地址或端口號。由于存在單個服務程序與多個客戶程序通訊的可能,所以服務程序響應客戶程序不應該花 很多時間,否則客戶程序在得到服務前有可能花很多時間來等待通訊的建立,然而服務程序和客 戶程序的會話有可能是很長的(這與電話類似),因此為加快對客戶程序連接請求的響應,典型 的方法是服務器主機運行一個后臺線程,這個后臺線程處理服務程序和客戶程序的通訊。9為了示范我們在上面談到的慨念并完成 SSClient 程序,下面我們創(chuàng)建一個 SSSe
31、rver 程序, 程序?qū)?chuàng)建一個 ServerSocket 對象來監(jiān)聽端口 10000 的連接請求,如果成功服務程序?qū)⒌却?連接輸入,開始一個線程處理連接,并響應來自客戶程序的命令。下面就是這段程序的代碼:Listing 3: SSServer.java/ SSServer.javaimport java.io.*;import .*;import java.util.*;class SSServerpublic static void main (String args) throws IOExceptionSystem.out.println (Server startin
32、g.n);/ Create a server socket that listens for incoming connection/ requests on port 10000.ServerSocket server = new ServerSocket (10000);while (true)/ Listen for incoming connection requests from client/ programs, establish a connection, and return a Socket/ object that represents this connection.S
33、ocket s = server.accept ();System.out.println (Accepting Connection.n);/ Start a thread to handle the connection.new ServerThread (s).start ();10class ServerThread extends Threadprivate Socket s;ServerThread (Socket s)this.s = s; public void run ()BufferedReader br = null;PrintWriter pw = null;try/
34、Create an input stream reader that chains to the sockets/ byte-oriented input stream. The input stream reader/ converts bytes read from the socket to characters. The/ conversion is based on the platforms default character/ set.InputStreamReader isr;isr = new InputStreamReader (s.getInputStream ();/
35、Create a buffered reader that chains to the input stream/ reader. The buffered reader supplies a convenient method/ for reading entire lines of text.11br = new BufferedReader (isr);/ Create a print writer that chains to the sockets byte-/ oriented output stream. The print writer creates an/ intermed
36、iate output stream writer that converts/ characters sent to the socket to bytes. The conversion/ is based on the platforms default character set.pw = new PrintWriter (s.getOutputStream (), true);/ Create a calendar that makes it possible to obtain date/ and time information.Calendar c = Calendar.get
37、Instance ();/ Because the client program may send multiple commands, a/ loop is required. Keep looping until the client either/ explicitly requests termination by sending a command/ beginning with letters BYE or implicitly requests/ termination by closing its output stream.do/ Obtain the client prog
38、rams next command.String cmd = br.readLine ();/ Exit if client program has closed its output stream.if (cmd = null)break;12/ Convert command to uppercase, for ease of comparison.cmd = cmd.toUpperCase ();/ If client program sends BYE command, terminate.if (cmd.startsWith (BYE)break;/ If client progra
39、m sends DATE or TIME command, return/ current date/time to the client program.if (cmd.startsWith (DATE) | cmd.startsWith (TIME)pw.println (c.getTime ().toString ();/ If client program sends DOM (Day Of Month) command,/ return current day of month to the client program.if (cmd.startsWith (DOM)pw.prin
40、tln ( + c.get (Calendar.DAY_OF_MONTH);/ If client program sends DOW (Day Of Week) command,/ return current weekday (as a string) to the client/ program.if (cmd.startsWith (DOW)switch (c.get (Calendar.DAY_OF_WEEK)case Calendar.SUNDAY : pw.println (SUNDAY);break;case Calendar.MONDAY : pw.println (MOND
41、AY);13break;case Calendar.TUESDAY : pw.println (TUESDAY);break;case Calendar.WEDNESDAY: pw.println (WEDNESDAY);break;case Calendar.THURSDAY : pw.println (THURSDAY);break;case Calendar.FRIDAY : pw.println (FRIDAY);break;case Calendar.SATURDAY : pw.println (SATURDAY);/ If client program sends DOY (Day
42、 of Year) command,/ return current day of year to the client program.if (cmd.startsWith (DOY)pw.println ( + c.get (Calendar.DAY_OF_YEAR);/ If client program sends PAUSE command, sleep for three/ seconds.if (cmd.startsWith (PAUSE)tryThread.sleep (3000);14catch (InterruptedException e)while (true);cat
43、ch (IOException e)System.out.println (e.toString ();finallySystem.out.println (Closing Connection.n);tryif (br != null)br.close ();if (pw != null)pw.close ();if (s != null)s.close ();15運行這段程序?qū)⒌玫较旅娴妮敵觯篠erver starting.Accepting Connection.Closing Connection.SSServer 的源代碼聲明了一對類:SSServer 和 ServerThread;
44、SSServer 的 main()方法創(chuàng)建了一個 ServerSocket 對象來監(jiān)聽端口 10000 上的連接請求,如果成功, SSServer 進入一個無限循環(huán)中,交替調(diào)用 ServerSocket 的 accept() 方法來等待連接請求,同時啟動 后臺線程處理連接(accept()返回的請求)。線程由 ServerThread 繼承的 start ()方法開始, 并執(zhí)行 ServerThread 的 run()方法中的代碼。一旦 run()方法運行,線程將創(chuàng)建 BufferedReader, PrintWriter 和 Calendar 對象并進 入一個循環(huán),這個循環(huán)由讀(通過 Buf
45、feredReader 的 readLine())來自客戶程序的一行文本 開始,文本(命令)存儲在 cmd 引用的 string 對象中,如果客戶程序過早的關(guān)閉輸出流,會發(fā) 生什么呢?答案是:cmd 將得不到賦值。注意必須考慮到這種情況:在服務程序正在讀輸入流時,客戶程序關(guān)閉了輸出流,如果沒 有對這種情況進行處理,那么程序?qū)a(chǎn)生異常。一旦編譯了 SSServer 的源代碼,通過輸入 Java SSServer 來運行程序,在開始運行SSServer 后,就可以運行一個或多個 SSClient 程序。三、Java網(wǎng)絡編程精解之ServerSocket用法詳解一 1在客戶/服務器通信模式中,服務器
46、端需要創(chuàng)建監(jiān)聽特定端口的 ServerSocket, ServerSocket 負責接收客戶連接請求。本章首先介紹 ServerSocket 類的各個構(gòu)造方法,以 及成員方法的用法,接著介紹服務器如何用多線程來處理與多個客戶的通信任務。16本章提供線程池的一種實現(xiàn)方式。線程池包括一個工作隊列和若干工作線程。服務器程序 向工作隊列中加入與客戶通信的任務,工作線程不斷從工作隊列中取出任務并執(zhí)行它。本章還介 紹了 java.util.concurrent 包中的線程池類的用法,在服務器程序中可以直接使用它們。3.1 構(gòu)造 ServerSocketServerSocket 的構(gòu)造方法有以下幾種重載形式
47、:ServerSocket()throws IOExceptionServerSocket(int port) throws IOExceptionServerSocket(int port, int backlog) throws IOExceptionServerSocket(int port, int backlog, InetAddress bindAddr) throws IOException在以上構(gòu)造方法中,參數(shù) port 指定服務器要綁定的端口(服務器要監(jiān)聽的端口),參數(shù)backlog 指定客戶連接請求隊列的長度,參數(shù) bindAddr 指定服務器要綁定的 IP 地址。3.1.
48、1 綁定端口 除了第一個不帶參數(shù)的構(gòu)造方法以外,其他構(gòu)造方法都會使服務器與特定端口綁定,該端口由參數(shù) port 指定。例如,以下代碼創(chuàng)建了一個與 80 端口綁定的服務器:ServerSocket serverSocket=new ServerSocket(80);如果運行時無法綁定到 80 端口,以上代碼會拋出 IOException,更確切地說,是拋出BindException,它是 IOException 的子類。BindException 一般是由以下原因造成的:端口已經(jīng)被其他服務器進程占用;在某些操作系統(tǒng)中,如果沒有以超級用戶的身份來運行服務器程序,那么操作系統(tǒng)不允許服務 器綁定到 1
49、1023 之間的端口。如果把參數(shù) port 設(shè)為 0,表示由操作系統(tǒng)來為服務器分配一個任意可用的端口。由操作系 統(tǒng)分配的端口也稱為匿名端口。對于多數(shù)服務器,會使用明確的端口,而不會使用匿名端口,因 為客戶程序需要事先知道服務器的端口,才能方便地訪問服務器。在某些場合,匿名端口有著特 殊的用途。3.1.2 設(shè)定客戶連接請求隊列的長度 當服務器進程運行時,可能會同時監(jiān)聽到多個客戶的連接請求。例如,每當一個客戶進程執(zhí)行以下代碼:Socket socket=new Socket(,80);就意味著在遠程主機的 80 端口上,監(jiān)
50、聽到了一個客戶的連接請求。管理客戶連接請求的任務是由操作系統(tǒng)來完成的。操作系統(tǒng)把這些連接請求存儲在一個先進先出 的隊列中。許多操作系統(tǒng)限定了隊列的最大長度,一般為 50。當隊列中的連接請求達到了隊列 的最大容量時,服務器進程所在的主機會拒絕新的連接請求。只有當服務器進程通過17ServerSocket的accept()方法從隊列中取出連接請求,使隊列騰出空位時,隊列才能繼續(xù)加入 新的連接請求。對于客戶進程,如果它發(fā)出的連接請求被加入到服務器的隊列中,就意味著客戶與服務器 的連接建立成功,客戶進程從 Socket 構(gòu)造方法中正常返回。如果客戶進程發(fā)出的連接請求被服 務器拒絕,Socket 構(gòu)造方
51、法就會拋出 ConnectionException。ServerSocket 構(gòu)造方法的 backlog 參數(shù)用來顯式設(shè)置連接請求隊列的長度,它將覆蓋操 作系統(tǒng)限定的隊列的最大長度。值得注意的是,在以下幾種情況中,仍然會采用操作系統(tǒng)限定的 隊列的最大長度:backlog 參數(shù)的值大于操作系統(tǒng)限定的隊列的最大長度;backlog 參數(shù)的值小于或等于 0;在 ServerSocket 構(gòu)造方法中沒有設(shè)置 backlog 參數(shù)。以下例程 3-1 的 Client.java 和例程 3-2 的 Server.java 用來演示服務器的連接請求隊列 的特性。例程 3-1 Client.javaimpor
52、t .*;public class Client public static void main(String args)throws Exceptionfinal int length=100;String host=localhost;int port=8000;Socket sockets=new Socketlength;for(int i=0;isocketsi=new Socket(host, port);System.out.println(第+(i+1)+次連接成功);Thread.sleep(3000);for(int i=0;isocketsi.close(
53、);/斷開連接18例程 3-2 Server.javaimport java.io.*;import .*;public class Server private int port=8000;private ServerSocket serverSocket;public Server() throws IOException serverSocket = new ServerSocket(port,3);/連接請求隊列的長度為 3System.out.println(服務器啟動);public void service() while (true) Socket socket=null;try socket = serverSocket.accept();/從連接請求隊列中取出一個連接System.out.println(New connection accepted +socket.getInetAddress() + : +socket.getPort();catch (IOException e) e.printStackTrace();finally tryif(socket!=null)socket.close(
溫馨提示
- 1. 本站所有資源如無特殊說明,都需要本地電腦安裝OFFICE2007和PDF閱讀器。圖紙軟件為CAD,CAXA,PROE,UG,SolidWorks等.壓縮文件請下載最新的WinRAR軟件解壓。
- 2. 本站的文檔不包含任何第三方提供的附件圖紙等,如果需要附件,請聯(lián)系上傳者。文件的所有權(quán)益歸上傳用戶所有。
- 3. 本站RAR壓縮包中若帶圖紙,網(wǎng)頁內(nèi)容里面會有圖紙預覽,若沒有圖紙預覽就沒有圖紙。
- 4. 未經(jīng)權(quán)益所有人同意不得將文件中的內(nèi)容挪作商業(yè)或盈利用途。
- 5. 人人文庫網(wǎng)僅提供信息存儲空間,僅對用戶上傳內(nèi)容的表現(xiàn)方式做保護處理,對用戶上傳分享的文檔內(nèi)容本身不做任何修改或編輯,并不能對任何下載內(nèi)容負責。
- 6. 下載文件中如有侵權(quán)或不適當內(nèi)容,請與我們聯(lián)系,我們立即糾正。
- 7. 本站不保證下載資源的準確性、安全性和完整性, 同時也不承擔用戶因使用這些下載資源對自己和他人造成任何形式的傷害或損失。
最新文檔
- 2024房屋抵押貸款擔保補充合同版B版
- 2025租房定金合同范本
- 2025年度智能穿戴設(shè)備研發(fā)與生產(chǎn)技術(shù)服務分包合同3篇
- 2025版?zhèn)}儲庫房租賃合同范本(含倉儲物流服務)2篇
- 2025學校食堂承包合同范本
- 2025版綠色建筑評價標識施工合同規(guī)范文本(完整版)3篇
- 2025版電子元器件打磨工勞動合同范本2篇
- 2025版電商平臺商品退換貨及售后服務合同范本3篇
- 2025pe燃氣管材銷售合同書
- 2024招投標與合同管理法律法規(guī)與實務操作習題解析15篇
- 《金融工程原理-無套利均衡分析》筆記01
- 工程項目收尾管理辦法
- 閘門及啟閉機安裝專項施工方案
- 應征公民體格檢查表(征兵)
- 電力系統(tǒng)分析名詞解釋、簡答、模擬試卷
- 家具制造企業(yè)消防安全要求
- 鋼筋位置及保護層厚度檢測ppt課件
- 巖石堅固性和穩(wěn)定性分級表
- 控制網(wǎng)復測及控制點加密復測報告課件
- CNC程序控制管理辦法
- 案例思念休閑吧
評論
0/150
提交評論