版權(quán)說明:本文檔由用戶提供并上傳,收益歸屬內(nèi)容提供方,若內(nèi)容存在侵權(quán),請進(jìn)行舉報(bào)或認(rèn)領(lǐng)
文檔簡介
1、 面向套接字(Socket)Java編程(單線程+多線程)學(xué)習(xí)+技術(shù)2010-05-24 22:49:15閱讀622評論0字號:大中小訂閱1使用套接字實(shí)現(xiàn)基于TCP協(xié)議的服務(wù)器和客戶機(jī)程序(單線程)依據(jù)TCP協(xié)議,在C/S架構(gòu)的通訊過程中,客戶端和服務(wù)器的Socket動(dòng)作如下:客戶端:1. 用服務(wù)器的IP地址和端口號實(shí)例化Socket對象。2. 調(diào)用connect方法,連接到服務(wù)器上。3. 將發(fā)送到服務(wù)器的IO流填充到IO對象里,比如BufferedReader/PrintWriter。4. 利用Socket提供的getInputStream和getOutputStream方法,通過IO流對象
2、,向服務(wù)器發(fā)送數(shù)據(jù)流。5. 通訊完成后,關(guān)閉打開的IO對象和Socket。服務(wù)器:1. 在服務(wù)器,用一個(gè)端口來實(shí)例化一個(gè)ServerSocket對象。此時(shí),服務(wù)器就可以這個(gè)端口時(shí)刻監(jiān)聽從客戶端發(fā)來的連接請求。2. 調(diào)用ServerSocket的accept方法,開始監(jiān)聽連接從端口上發(fā)來的連接請求。3. 利用accept方法返回的客戶端的Socket對象,進(jìn)行讀寫IO的操作通訊完成后,關(guān)閉打開的流和Socket對象。1.1開發(fā)服務(wù)端代碼根據(jù)上面描述的通訊流程,我們可以按如下的步驟設(shè)計(jì)服務(wù)器端的代碼。第一步,依次點(diǎn)擊Eclipse環(huán)境里的“文件”|“新建”|“項(xiàng)目”選項(xiàng),進(jìn)入“新建項(xiàng)目”的向?qū)υ?/p>
3、框,在其中選中“Java項(xiàng)目”,點(diǎn)擊“下一步”按鈕,在隨后彈出的對話框里,在其中的“項(xiàng)目名”一欄里,輸入項(xiàng)目名“TCPSocket”,其它的選項(xiàng)目選擇系統(tǒng)默認(rèn)值,再按“完成”按鈕,結(jié)束創(chuàng)建Java項(xiàng)目的動(dòng)作。第二步,完成創(chuàng)建項(xiàng)目后,選中集成開發(fā)環(huán)境左側(cè)的項(xiàng)目名“TCPSocket”,點(diǎn)擊右鍵,在隨后彈出的菜單里依次選擇“新建”!“類”的選項(xiàng),創(chuàng)建服務(wù)器類的代碼。在隨后彈出的“新建Java類”的對話框里,輸入包名“tcp”,輸入文件名“ServerCode”,請注意大小寫,在“修飾符”里選中“公用”,在“想要?jiǎng)?chuàng)建哪些方法存根”下,選中“public static void main(String
4、 args )”單選框,同時(shí)把其它兩項(xiàng)目取消掉,再按“完成”按鈕,可以生成代碼。第三步,在生成的代碼里,編寫引入Java包的代碼,只有當(dāng)我們引入這些包后,我們才能調(diào)用這些包里提供的IO和Socket類的方法。package tcp;import java.io.BufferedReader;import java.io.BufferedWriter;import java.io.IOException;import java.io.InputStreamReader;import java.io.OutputStreamWriter;import java.io.PrintWriter;imp
5、ort .ServerSocket;import .Socket;第四步,編寫服務(wù)器端的主體代碼,如下所示。 public class ServerCode /設(shè)置端口號 public static int portNo = 3333; public static void main(String args) throws IOException ServerSocket s = new ServerSocket(portNo); System.out.println(The Server is start: + s); / 阻塞,直到有客戶端連接Socket
6、socket = s.accept(); try System.out.println(Accept the Client: + socket); /設(shè)置IO句柄 BufferedReader in = new BufferedReader(new InputStreamReader(socket .getInputStream(); PrintWriter out = new PrintWriter(new BufferedWriter( new OutputStreamWriter(socket.getOutputStream(), true); while (true) String s
7、tr = in.readLine(); if (str.equals(byebye) break; System.out.println(In Server reveived the info: + str); out.println(str); finally System.out.println(close the Server socket and the io.); socket.close(); s.close(); 這段代碼的主要業(yè)務(wù)邏輯是:1. 在上述代碼里的main函數(shù)前,我們設(shè)置了通訊所用到的端口號,為3333。2. 在main函數(shù)里,根據(jù)給定3333端口號,初始化一個(gè)Ser
8、verSocket對象s,該對象用來承擔(dān)服務(wù)器端監(jiān)聽連接和提供通訊服務(wù)的功能。3. 調(diào)用ServerSocket對象的accept方法,監(jiān)聽從客戶端的連接請求。當(dāng)完成調(diào)用accept方法后,整段服務(wù)器端代碼將回阻塞在這里,直到客戶端發(fā)來connect請求。4. 當(dāng)客戶端發(fā)來connect請求,或是通過構(gòu)造函數(shù)直接把客戶端的Socket對象連接到服務(wù)器端后,阻塞于此的代碼將會(huì)繼續(xù)運(yùn)行。此時(shí)服務(wù)器端將會(huì)根據(jù)accept方法的執(zhí)行結(jié)果,用一個(gè)Socket對象來描述客戶端的連接句柄。5. 創(chuàng)建兩個(gè)名為in和out的對象,用來傳輸和接收通訊時(shí)的數(shù)據(jù)流。6. 創(chuàng)建一個(gè)while(true)的死循環(huán),在這個(gè)
9、循環(huán)里,通過in.readLine()方法,讀取從客戶端發(fā)送來的IO流(字符串),并打印出來。如果讀到的字符串是“byebye”,那么退出while循環(huán)。7. 在trycatchfinally語句段里,不論在try語句段里是否發(fā)生異常,并且不論這些異常的種類,finally從句都將會(huì)被執(zhí)行到。在finally從句里,將關(guān)閉描述客戶端的連接句柄socket對象和ServerSocket類型的s對象。1.2開發(fā)客戶端代碼我們可以按以下的步驟,開發(fā)客戶端的代碼。第一,在TCPSocket項(xiàng)目下的tcp包下,創(chuàng)建一個(gè)名為ClientCode.java的文件。在其中編寫引入Java包的代碼,如下所示:
10、package tcp;import java.io.BufferedReader;import java.io.BufferedWriter;import java.io.IOException;import java.io.InputStreamReader;import java.io.OutputStreamWriter;import java.io.PrintWriter;import .InetAddress;import .Socket;第二,編寫客戶端的主體代碼,如下所示:public class ClientCode static String
11、 clientName = Mike; /端口號public static int portNo = 3333; public static void main(String args) throws IOException / 設(shè)置連接地址類,連接本地 InetAddress addr = InetAddress.getByName(localhost); /要對應(yīng)服務(wù)器端的3333端口號 Socket socket = new Socket(addr, portNo); trySystem.out.println(socket = + socket); / 設(shè)置IO句柄 BufferedR
12、eader in = new BufferedReader(new InputStreamReader(socket .getInputStream(); PrintWriter out = new PrintWriter(new BufferedWriter( new OutputStreamWriter(socket.getOutputStream(), true); out.println(Hello Server,I am + clientName); String str = in.readLine(); System.out.println(str); out.println(by
13、ebye); finally System.out.println(close the Client socket and the io.); socket.close(); 上述客戶端代碼的主要業(yè)務(wù)邏輯是:1. 同樣定義了通訊端口號,這里給出的端口號必須要和服務(wù)器端的一致。2. 在main函數(shù)里,根據(jù)地址信息“l(fā)ocalhost”,創(chuàng)建一個(gè)InetAddress類型的對象addr。這里,因?yàn)槲覀儼芽蛻舳撕头?wù)器端的代碼都放在本機(jī)運(yùn)行,所以同樣可以用“”字符串,來創(chuàng)建InetAddress對象。3. 根據(jù)addr和端口號信息,創(chuàng)建一個(gè)Socket類型對象,該對象用來同服務(wù)器端
14、的ServerSocket類型對象交互,共同完成C/S通訊流程。4. 同樣地創(chuàng)建in和out兩類IO句柄,用來向服務(wù)器端發(fā)送和接收數(shù)據(jù)流。5. 通過out對象,向服務(wù)器端發(fā)送Hello Server,I am 的字符串。發(fā)送后,同樣可以用in句柄,接收從服務(wù)器端的消息。6. 利用out對象,發(fā)送”byebye”字符串,用以告之服務(wù)器端,本次通訊結(jié)束。7. 在finally從句里,關(guān)閉Socket對象,斷開同服務(wù)器端的連接。1.3運(yùn)行效果演示在上述兩部分里,我們分別講述了C/S通訊過程中服務(wù)器端和客戶端代碼的業(yè)務(wù)邏輯,下面我們將在集成開發(fā)環(huán)境里,演示這里通訊流程。第一步,選中ServerCode
15、.java代碼,在eclipse的“運(yùn)行”菜單里,選中“運(yùn)行方式”|“1 Java應(yīng)用程序”的菜單,開啟服務(wù)器端的程序。開啟服務(wù)端程序后,會(huì)在eclipse環(huán)境下方的控制臺里顯示如下的內(nèi)容:The Server is start: ServerSocketaddr=/,port=0,localport=3333在這里,由于ServerSocket對象并沒監(jiān)聽到客戶端的請求,所以addr和后面的port值都是初始值。第二步,按同樣的方法,打開ClientCode.java程序,啟動(dòng)客戶端。啟動(dòng)以后,將在客戶端的控制臺里看到如下的信息:socket = Socketad
16、dr=localhost/,port=3333,localport=1326Hello Server,I am Mikeclose the Client socket and the io.從中可以看到,在第一行里,顯示客戶端Socket對象連接的IP地址和端口號,在第二行里,可以到到客戶端向服務(wù)器端發(fā)送的字符串,而在第三行里,可以看到通訊結(jié)束后,客戶端關(guān)閉連接Socket和IO對象的提示語句。第三步,在eclipse下方的控制臺里,切換到ServerCode服務(wù)端的控制臺提示信息里,我們可以看到服務(wù)器端在接收到客戶端連接請求后的響應(yīng)信息。響應(yīng)的信息如下所示:The Serv
17、er is start: ServerSocketaddr=/,port=0,localport=3333Accept the Client: Socketaddr=/,port=1327,localport=3333In Server reveived the info: Hello Server,I am Mikeclose the Server socket and the io.其中,第一行是啟動(dòng)服務(wù)器程序后顯示的信息。在第二行里,顯示從客戶端發(fā)送的連接請求的各項(xiàng)參數(shù)。在第三行里,顯示了從客戶端發(fā)送過來的字符串。在第四行里,顯示了關(guān)閉服務(wù)器
18、端ServerSocket和IO對象的提示信息。從中我們可以看出在服務(wù)器端里accept阻塞和繼續(xù)運(yùn)行的這個(gè)過程。通過上述的操作,我們可以詳細(xì)地觀察到C/S通訊的全部流程,請大家務(wù)必要注意:一定要先開啟服務(wù)器端的程序再開啟客戶端,如果這個(gè)步驟做反的話,客戶端程序會(huì)應(yīng)找不到服務(wù)器端而報(bào)異常。2使用套接字連接多個(gè)客戶機(jī)(多線程)在7.1的代碼里,客戶端和服務(wù)器之間只有一個(gè)通訊線程,所以它們之間只有一條Socket信道。如果我們在通過程序里引入多線程的機(jī)制,可讓一個(gè)服務(wù)器端同時(shí)監(jiān)聽并接收多個(gè)客戶端的請求,并同步地為它們提供通訊服務(wù)。基于多線程的通訊方式,將大大地提高服務(wù)器端的利用效率,并能使服務(wù)器端
19、能具備完善的服務(wù)功能。2.1開發(fā)服務(wù)端代碼我們可以按以下的步驟開發(fā)基于多線程的服務(wù)器端的代碼。第一步,在3.2里創(chuàng)建的“TCPSocket”項(xiàng)目里,新建一個(gè)名為ThreadServer.java的代碼文件,創(chuàng)建文件的方式大家可以參照3.2部分的描述。首先編寫package和import部分的代碼,用來打包和引入包文件,如下所示:package tcp;import java.io.*;import .*;第二步,由于我們在服務(wù)器端引入線程機(jī)制,所以我們要編寫線程代碼的主體執(zhí)行類ServerThreadCode,這個(gè)類的代碼如下所示:class ServerThreadCode
20、extends Thread /客戶端的socket private Socket clientSocket; /IO句柄 private BufferedReader sin; private PrintWriter sout; /默認(rèn)的構(gòu)造函數(shù) public ServerThreadCode() public ServerThreadCode(Socket s) throws IOException clientSocket = s; /初始化sin和sout的句柄 sin = new BufferedReader(new InputStreamReader(clientSocket .g
21、etInputStream();sout = new PrintWriter(new BufferedWriter(new OutputStreamWriter( clientSocket.getOutputStream(), true); /開啟線程 start(); /線程執(zhí)行的主體函數(shù) public void run() try /用循環(huán)來監(jiān)聽通訊內(nèi)容 for(;) String str = sin.readLine(); /如果接收到的是byebye,退出本次通訊 if (str.equals(byebye) break; System.out.println(In Server re
22、veived the info: + str); sout.println(str); System.out.println(closing the server socket!); catch (IOException e) e.printStackTrace(); finally System.out.println(close the Server socket and the io.); try clientSocket.close(); catch (IOException e) e.printStackTrace(); 這個(gè)類的業(yè)務(wù)邏輯說明如下:1. 這個(gè)類通過繼承Thread類來
23、實(shí)現(xiàn)線程的功能,也就是說,在其中的run方法里,定義了該線程啟動(dòng)后要執(zhí)行的業(yè)務(wù)動(dòng)作。2. 這個(gè)類提供了兩種類型的重載函數(shù)。在參數(shù)類型為Socket的構(gòu)造函數(shù)里,通過參數(shù),初始化了本類里的Socket對象,同時(shí)實(shí)例化了兩類IO對象。在此基礎(chǔ)上,通過start方法,啟動(dòng)定義在run方法內(nèi)的本線程的業(yè)務(wù)邏輯。3. 在定義線程主體動(dòng)作的run方法里,通過一個(gè)for(;)類型的循環(huán),根據(jù)IO句柄,讀取從Socket信道上傳輸過來的客戶端發(fā)送的通訊信息。如果得到的信息為“byebye”,則表明本次通訊結(jié)束,退出for循環(huán)。4. catch從句將處理在try語句里遇到的IO錯(cuò)誤等異常,而在finally從句
24、里,將在通訊結(jié)束后關(guān)閉客戶端的Socket句柄。上述的線程主體代碼將會(huì)在ThreadServer類里被調(diào)用。第三步,編寫服務(wù)器端的主體類ThreadServer,代碼如下所示:public class ThreadServer /端口號 static final int portNo = 3333; public static void main(String args) throws IOException /服務(wù)器端的socket ServerSocket s = new ServerSocket(portNo); System.out.println(The Server is star
25、t: + s); try for(;) /阻塞,直到有客戶端連接 Socket socket = s.accept(); /通過構(gòu)造函數(shù),啟動(dòng)線程 new ServerThreadCode(socket); finally s.close(); 這段代碼的主要業(yè)務(wù)邏輯說明如下:1. 首先定義了通訊所用的端口號,為3333。2. 在main函數(shù)里,根據(jù)端口號,創(chuàng)建一個(gè)ServerSocket類型的服務(wù)器端的Socket,用來同客戶端通訊。3. 在for(;)的循環(huán)里,調(diào)用accept方法,監(jiān)聽從客戶端請求過來的socket,請注意這里又是一個(gè)阻塞。當(dāng)客戶端有請求過來時(shí),將通過ServerThre
26、adCode的構(gòu)造函數(shù),創(chuàng)建一個(gè)線程類,用來接收客戶端發(fā)送來的字符串。在這里我們可以再一次觀察ServerThreadCode類,在其中,這個(gè)類通過構(gòu)造函數(shù)里的start方法,開啟run方法,而在run方法里,是通過sin對象來接收字符串,通過sout對象來輸出。4. 在finally從句里,關(guān)閉服務(wù)器端的Socket,從而結(jié)束本次通訊。2.2開發(fā)客戶端代碼我們可以按以下的步驟,編寫的基于多線程的客戶端代碼。第一步,在“TCPSocket”項(xiàng)目里,新建一個(gè)名為ThreadClient.java的代碼文件。同樣是編寫package和import部分的代碼,用來打包和引入包文件,如下所示:pack
27、age tcp;import .*;import java.io.*;第二步,編寫線程執(zhí)行主體的ClientThreadCode類,同樣,這個(gè)類通過繼承Thread來實(shí)現(xiàn)線程的功能。class ClientThreadCode extends Thread /客戶端的socket private Socket socket; /線程統(tǒng)計(jì)數(shù),用來給線程編號 private static int cnt = 0; private int clientId = cnt+; private BufferedReader in; private PrintWriter out; /構(gòu)造函
28、數(shù) public ClientThreadCode(InetAddress addr) try socket = new Socket(addr, 3333); catch(IOException e) e.printStackTrace(); /實(shí)例化IO對象try in = new BufferedReader( new InputStreamReader(socket.getInputStream(); out = new PrintWriter( new BufferedWriter(new OutputStreamWriter(socket.getOutputStream(), tr
29、ue); /開啟線程 start(); catch(IOException e) /出現(xiàn)異常,關(guān)閉socket try socket.close(); catch(IOException e2) e2.printStackTrace(); /線程主體方法public void run() try out.println(Hello Server,My id is + clientId ); String str = in.readLine(); System.out.println(str); out.println(byebye); catch(IOException e) e.printS
30、tackTrace(); finally try socket.close(); catch(IOException e) e.printStackTrace(); 這個(gè)類的主要業(yè)務(wù)邏輯是:1. 在構(gòu)造函數(shù)里,通過參數(shù)類型為InetAddress類型參數(shù)和3333,初始化了本類里的Socket對象,隨后實(shí)例化了兩類IO對象,并通過start方法,啟動(dòng)定義在run方法內(nèi)的本線程的業(yè)務(wù)邏輯。2. 在定義線程主體動(dòng)作的run方法里,通過IO句柄,向Socket信道上傳輸本客戶端的ID號,發(fā)送完畢后,傳輸”byebye”字符串,向服務(wù)器端表示本線程的通訊結(jié)束。3. 同樣地,catch從句將處理在try
31、語句里遇到的IO錯(cuò)誤等異常,而在finally從句里,將在通訊結(jié)束后關(guān)閉客戶端的Socket句柄。第三步,編寫客戶端的主體代碼,在這段代碼里,將通過for循環(huán),根據(jù)指定的待創(chuàng)建的線程數(shù)量,通過ClientThreadCode的構(gòu)造函數(shù),創(chuàng)建若干個(gè)客戶端線程,同步地和服務(wù)器端通訊。public class ThreadClient public static void main(String args) throws IOException, InterruptedException int threadNo = 0; InetAddress addr = InetAddress.getByNa
32、me(localhost); for(threadNo = 0;threadNo3;threadNo+) new ClientThreadCode(addr); 這段代碼執(zhí)行以后,在客戶端將會(huì)有3個(gè)通訊線程,每個(gè)線程首先將先向服務(wù)器端發(fā)送Hello Server,My id is 的字符串,然后發(fā)送”byebye”,終止該線程的通訊。2.3運(yùn)行效果演示接下來,我們來觀察一下基于多線程的C/S架構(gòu)的運(yùn)行效果。第一步,我們先要啟動(dòng)服務(wù)器端的ThreadServer代碼,啟動(dòng)后,在控制臺里會(huì)出現(xiàn)如下的提示信息:The Server is start: ServerSocketaddr=
33、/,port=0,localport=3333上述的提示信息里,我們同樣可以看到,服務(wù)器在開啟服務(wù)后,會(huì)阻塞在accept這里,直到有客戶端請求過來。第二步,我們在啟動(dòng)完服務(wù)器后,運(yùn)行客戶端的ThreadClient.java代碼,運(yùn)行后,我們觀察服務(wù)器端的控制臺,會(huì)出現(xiàn)如下的信息:The Server is start: ServerSocketaddr=/,port=0,localport=3333In Server reveived the info: Hello Server,My id is 0In Server reveived the i
34、nfo: Hello Server,My id is 1In Server reveived the info: Hello Server,My id is 2closing the server socket!close the Server socket and the io.closing the server socket!close the Server socket and the io.closing the server socket!close the Server socket and the io.其中,第一行是原來就有,在后面的幾行里,首先將會(huì)輸出了從客戶端過來的線程請
35、求信息,比如In Server reveived the info: Hello Server,My id is 0接下來則會(huì)顯示關(guān)閉Server端的IO和Socket的提示信息。這里,請大家注意,由于線程運(yùn)行的不確定性,從第二行開始的打印輸出語句的次序是不確定的。但是,不論輸出語句的次序如何變化,我們都可以從中看到,客戶端有三個(gè)線程請求過來,并且,服務(wù)器端在處理完請求后,會(huì)關(guān)閉Socker和IO。第三步,當(dāng)我們運(yùn)行完ThreadClient.java的代碼后,并切換到ThreadClient.java的控制臺,我們可以看到如下的輸出:Hello Server,My id is 0Hello
36、Server,My id is 2Hello Server,My id is 1這說明在客戶端開啟了3個(gè)線程,并利用這3個(gè)線程,向服務(wù)器端發(fā)送字符串。而在服務(wù)器端,用accept方法分別監(jiān)聽到了這3個(gè)線程,并與之對應(yīng)地也開了3個(gè)線程與之通訊。3UDP協(xié)議與傳輸數(shù)據(jù)報(bào)文UDP協(xié)議一般應(yīng)用在 “群發(fā)信息”的場合,所以它更可以利用多線程的機(jī)制,實(shí)現(xiàn)多信息的同步發(fā)送。為了改善代碼的架構(gòu),我們更可以把一些業(yè)務(wù)邏輯的動(dòng)作抽象成方法,并封裝成類,這樣,基于UDP功能的類就可以在其它應(yīng)用項(xiàng)目里被輕易地重用。3.1開發(fā)客戶端代碼如果我們把客戶端的所有代碼都寫在一個(gè)文件中,那么代碼的功能很有可能都聚集在一個(gè)方法力
37、,代碼的可維護(hù)性將會(huì)變得很差。所以我們專門設(shè)計(jì)了ClientBean類,在其中封裝了客戶端通訊的一些功能方法,在此基礎(chǔ)上,通過UDPClient.java文件,實(shí)現(xiàn)UDP客戶端的功能。另外,在這里以及以后的代碼里,我們不再詳細(xì)講述用Eclipse開發(fā)和運(yùn)行Java程序的方法,而是重點(diǎn)講述Java代碼的業(yè)務(wù)邏輯和主要工作流程。首先,我們可以按如下的步驟,設(shè)計(jì)ClientBean這個(gè)類。通過import語句,引入所用到的類庫,代碼如下所示。import java.io.IOException;import .DatagramPacket;import .Datagr
38、amSocket;import .InetAddress;import .SocketException;import .UnknownHostException;第二,定義ClientBean所用到的變量,并給出針對這些變量操作的get和set類型的方法,代碼如下所示。/描述UDP通訊的DatagramSocket對象private DatagramSocket ds;/用來封裝通訊字符串private byte buffer;/客戶端的端口號private int clientport ;/服務(wù)器端的端口號private int server
39、port;/通訊內(nèi)容private String content;/描述通訊地址private InetAddress ia;/以下是各屬性的Get和Set類型方法public byte getBuffer() return buffer;public void setBuffer(byte buffer) this.buffer = buffer;public int getClientport()return clientport;public void setClientport(int clientport) this.clientport = clientport;public St
40、ring getContent() return content;public void setContent(String content) this.content = content;public DatagramSocket getDs() return ds;public void setDs(DatagramSocket ds) this.ds = ds;public InetAddress getIa() return ia;public void setIa(InetAddress ia) this.ia = ia;public int getServerport() retu
41、rn serverport;public void setServerport(int serverport)this.serverport = serverport;在上述的代碼里,我們定義了描述用來實(shí)現(xiàn)UDP通訊的DatagramSocket類型對象ds,描述客戶端和服務(wù)器端的端口號clientport和serverport,用于描述通訊信息的buffer和content對象,其中,buffer對象是byte數(shù)組類型的,可通過UDP的數(shù)據(jù)報(bào)文傳輸,而content是String類型的,在應(yīng)用層面表示用戶之間的通訊內(nèi)容,另外還定義了InetAddress類型的ia變量,用來封裝通訊地址信息。
42、在隨后定義的一系列g(shù)et和set方法里,給出了設(shè)置和獲取上述變量的方法。第三,編寫該類的構(gòu)造函數(shù),代碼如下所示。public ClientBean() throws SocketException, UnknownHostException buffer = new byte1024; clientport = 1985; serverport = 1986; content = ; ds = new DatagramSocket(clientport); ia = InetAddress.getByName(localhost);在這個(gè)構(gòu)造函數(shù)里,我們給各變量賦予了初始值,其中分別設(shè)置了客戶
43、端和服務(wù)器端的端口號分別為1985和1985,設(shè)置了通訊連接地址為本地,并根據(jù)客戶端的端口號初始化了DatagramSocket對象。當(dāng)程序員初始化ClientBean類時(shí),這段構(gòu)造函數(shù)會(huì)自動(dòng)執(zhí)行,完成設(shè)置通訊各參數(shù)等工作。第四,編寫向服務(wù)器端發(fā)送消息的sendToServer方法,代碼如下所示。public void sendToServer() throws IOException buffer = content.getBytes(); ds.send(new DatagramPacket(buffer,content.length(),ia,serverport);在這段代碼里,根據(jù)S
44、tring類型的表示通訊信息的content變量,初始化UDP數(shù)據(jù)報(bào)文,即DatagramPacket對象,并通過調(diào)用DatagramSocket類型對象的send方法,發(fā)送該UDP報(bào)文。縱觀ClientBean類,我們可以發(fā)現(xiàn)在其中封裝了諸如通訊端口、通訊內(nèi)容和通訊報(bào)文等對象以及以UDP方式發(fā)送信息的sendToServer方法。所以,在UDPClient類里,可以直接調(diào)用其中的接口,方便地實(shí)現(xiàn)通訊功能。其次,我們可以按如下的步驟,設(shè)計(jì)UDPClient這個(gè)類。第一步,通過import語句,引入所用到的類庫,代碼如下所示。import java.io.BufferedReader;impor
45、t java.io.IOException;import java.io.InputStreamReader;第二步,編寫線程相關(guān)的代碼。由于我們要在UDP客戶端里通過多線程的機(jī)制,同時(shí)開多個(gè)客戶端,向服務(wù)器端發(fā)送通訊內(nèi)容,所以我們的UDPClient類必須要實(shí)現(xiàn)Runnable接口,并在其中覆蓋掉Runnable接口里的run方法。定義類和實(shí)現(xiàn)run方法的代碼如下所示。public class UDPClient implements Runnablepublic static String content;public static ClientBean client;public voi
46、d run() try client.setContent(content); client.sendToServer(); catch(Exception ex) System.err.println(ex.getMessage(); /end of run/main方法 /在上述代碼的run方法里,我們主要通過了ClientBean類里封裝的方法,設(shè)置了content內(nèi)容,并通過了sentToServer方法,將content內(nèi)容以數(shù)據(jù)報(bào)文的形式發(fā)送到服務(wù)器端。一旦線程被開啟,系統(tǒng)會(huì)自動(dòng)執(zhí)行定義在run方法里的動(dòng)作。第三步,編寫主方法。在步驟(2)里的/main方法注釋的位置,我們可以插入U(xiǎn)DPC
溫馨提示
- 1. 本站所有資源如無特殊說明,都需要本地電腦安裝OFFICE2007和PDF閱讀器。圖紙軟件為CAD,CAXA,PROE,UG,SolidWorks等.壓縮文件請下載最新的WinRAR軟件解壓。
- 2. 本站的文檔不包含任何第三方提供的附件圖紙等,如果需要附件,請聯(lián)系上傳者。文件的所有權(quán)益歸上傳用戶所有。
- 3. 本站RAR壓縮包中若帶圖紙,網(wǎng)頁內(nèi)容里面會(huì)有圖紙預(yù)覽,若沒有圖紙預(yù)覽就沒有圖紙。
- 4. 未經(jīng)權(quán)益所有人同意不得將文件中的內(nèi)容挪作商業(yè)或盈利用途。
- 5. 人人文庫網(wǎng)僅提供信息存儲(chǔ)空間,僅對用戶上傳內(nèi)容的表現(xiàn)方式做保護(hù)處理,對用戶上傳分享的文檔內(nèi)容本身不做任何修改或編輯,并不能對任何下載內(nèi)容負(fù)責(zé)。
- 6. 下載文件中如有侵權(quán)或不適當(dāng)內(nèi)容,請與我們聯(lián)系,我們立即糾正。
- 7. 本站不保證下載資源的準(zhǔn)確性、安全性和完整性, 同時(shí)也不承擔(dān)用戶因使用這些下載資源對自己和他人造成任何形式的傷害或損失。
最新文檔
- 飯店配菜知識培訓(xùn)課件
- 2024年電子元件訂購合同3篇
- 2024年環(huán)保產(chǎn)業(yè)債權(quán)轉(zhuǎn)股權(quán)項(xiàng)目合同范本3篇
- 中國計(jì)量大學(xué)《土木類專業(yè)概論》2023-2024學(xué)年第一學(xué)期期末試卷
- 2024年裝修工程進(jìn)度監(jiān)管協(xié)議版B版
- 長沙理工大學(xué)《運(yùn)作管理》2023-2024學(xué)年第一學(xué)期期末試卷
- 2024網(wǎng)絡(luò)設(shè)備安裝調(diào)試及維護(hù)合同
- 污水處理工程師的工作要點(diǎn)
- 環(huán)保實(shí)踐講座模板
- 展現(xiàn)實(shí)力的年度規(guī)劃計(jì)劃
- 第二章 熱力學(xué)基本定律
- 英語聽力考場建設(shè)方案
- 義務(wù)教育教科書英語Go for it七年級上冊單詞表
- 第一章 電力系統(tǒng)潮流計(jì)算1
- ICU常用鎮(zhèn)靜藥物介紹及藥學(xué)監(jiān)護(hù)
- 粉末丁腈橡膠使用方法
- 大氣課程設(shè)計(jì)-—袋式除塵器
- 蘇科版七年級生物學(xué)(上)教學(xué)工作總結(jié)
- 阿特拉斯擰緊機(jī)技術(shù)方案
- 中國人民財(cái)產(chǎn)保險(xiǎn)股份有限公司理賠稽查管理暫行辦法
- 鋼管、管件表面積計(jì)算公式(精編版)
評論
0/150
提交評論