面向套接字(Socket)Java編程講解_第1頁
面向套接字(Socket)Java編程講解_第2頁
面向套接字(Socket)Java編程講解_第3頁
面向套接字(Socket)Java編程講解_第4頁
面向套接字(Socket)Java編程講解_第5頁
已閱讀5頁,還剩14頁未讀, 繼續(xù)免費閱讀

下載本文檔

版權說明:本文檔由用戶提供并上傳,收益歸屬內容提供方,若內容存在侵權,請進行舉報或認領

文檔簡介

1、 面向套接字(Socket)Java編程(單線程+多線程)學習+技術2010-05-24 22:49:15閱讀622評論0字號:大中小訂閱1使用套接字實現(xiàn)基于TCP協(xié)議的服務器和客戶機程序(單線程)依據(jù)TCP協(xié)議,在C/S架構的通訊過程中,客戶端和服務器的Socket動作如下:客戶端:1. 用服務器的IP地址和端口號實例化Socket對象。2. 調用connect方法,連接到服務器上。3. 將發(fā)送到服務器的IO流填充到IO對象里,比如BufferedReader/PrintWriter。4. 利用Socket提供的getInputStream和getOutputStream方法,通過IO流對象

2、,向服務器發(fā)送數(shù)據(jù)流。5. 通訊完成后,關閉打開的IO對象和Socket。服務器:1. 在服務器,用一個端口來實例化一個ServerSocket對象。此時,服務器就可以這個端口時刻監(jiān)聽從客戶端發(fā)來的連接請求。2. 調用ServerSocket的accept方法,開始監(jiān)聽連接從端口上發(fā)來的連接請求。3. 利用accept方法返回的客戶端的Socket對象,進行讀寫IO的操作通訊完成后,關閉打開的流和Socket對象。1.1開發(fā)服務端代碼根據(jù)上面描述的通訊流程,我們可以按如下的步驟設計服務器端的代碼。第一步,依次點擊Eclipse環(huán)境里的“文件”|“新建”|“項目”選項,進入“新建項目”的向導對話

3、框,在其中選中“Java項目”,點擊“下一步”按鈕,在隨后彈出的對話框里,在其中的“項目名”一欄里,輸入項目名“TCPSocket”,其它的選項目選擇系統(tǒng)默認值,再按“完成”按鈕,結束創(chuàng)建Java項目的動作。第二步,完成創(chuàng)建項目后,選中集成開發(fā)環(huán)境左側的項目名“TCPSocket”,點擊右鍵,在隨后彈出的菜單里依次選擇“新建”!“類”的選項,創(chuàng)建服務器類的代碼。在隨后彈出的“新建Java類”的對話框里,輸入包名“tcp”,輸入文件名“ServerCode”,請注意大小寫,在“修飾符”里選中“公用”,在“想要創(chuàng)建哪些方法存根”下,選中“public static void main(String

4、 args )”單選框,同時把其它兩項目取消掉,再按“完成”按鈕,可以生成代碼。第三步,在生成的代碼里,編寫引入Java包的代碼,只有當我們引入這些包后,我們才能調用這些包里提供的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;第四步,編寫服務器端的主體代碼,如下所示。 public class ServerCode /設置端口號 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); /設置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è)務邏輯是:1. 在上述代碼里的main函數(shù)前,我們設置了通訊所用到的端口號,為3333。2. 在main函數(shù)里,根據(jù)給定3333端口號,初始化一個Ser

8、verSocket對象s,該對象用來承擔服務器端監(jiān)聽連接和提供通訊服務的功能。3. 調用ServerSocket對象的accept方法,監(jiān)聽從客戶端的連接請求。當完成調用accept方法后,整段服務器端代碼將回阻塞在這里,直到客戶端發(fā)來connect請求。4. 當客戶端發(fā)來connect請求,或是通過構造函數(shù)直接把客戶端的Socket對象連接到服務器端后,阻塞于此的代碼將會繼續(xù)運行。此時服務器端將會根據(jù)accept方法的執(zhí)行結果,用一個Socket對象來描述客戶端的連接句柄。5. 創(chuàng)建兩個名為in和out的對象,用來傳輸和接收通訊時的數(shù)據(jù)流。6. 創(chuàng)建一個while(true)的死循環(huán),在這個

9、循環(huán)里,通過in.readLine()方法,讀取從客戶端發(fā)送來的IO流(字符串),并打印出來。如果讀到的字符串是“byebye”,那么退出while循環(huán)。7. 在trycatchfinally語句段里,不論在try語句段里是否發(fā)生異常,并且不論這些異常的種類,finally從句都將會被執(zhí)行到。在finally從句里,將關閉描述客戶端的連接句柄socket對象和ServerSocket類型的s對象。1.2開發(fā)客戶端代碼我們可以按以下的步驟,開發(fā)客戶端的代碼。第一,在TCPSocket項目下的tcp包下,創(chuàng)建一個名為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 / 設置連接地址類,連接本地 InetAddress addr = InetAddress.getByName(localhost); /要對應服務器端的3333端口號 Socket socket = new Socket(addr, portNo); trySystem.out.println(socket = + socket); / 設置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è)務邏輯是:1. 同樣定義了通訊端口號,這里給出的端口號必須要和服務器端的一致。2. 在main函數(shù)里,根據(jù)地址信息“l(fā)ocalhost”,創(chuàng)建一個InetAddress類型的對象addr。這里,因為我們把客戶端和服務器端的代碼都放在本機運行,所以同樣可以用“”字符串,來創(chuàng)建InetAddress對象。3. 根據(jù)addr和端口號信息,創(chuàng)建一個Socket類型對象,該對象用來同服務器端

14、的ServerSocket類型對象交互,共同完成C/S通訊流程。4. 同樣地創(chuàng)建in和out兩類IO句柄,用來向服務器端發(fā)送和接收數(shù)據(jù)流。5. 通過out對象,向服務器端發(fā)送Hello Server,I am 的字符串。發(fā)送后,同樣可以用in句柄,接收從服務器端的消息。6. 利用out對象,發(fā)送”byebye”字符串,用以告之服務器端,本次通訊結束。7. 在finally從句里,關閉Socket對象,斷開同服務器端的連接。1.3運行效果演示在上述兩部分里,我們分別講述了C/S通訊過程中服務器端和客戶端代碼的業(yè)務邏輯,下面我們將在集成開發(fā)環(huán)境里,演示這里通訊流程。第一步,選中ServerCode

15、.java代碼,在eclipse的“運行”菜單里,選中“運行方式”|“1 Java應用程序”的菜單,開啟服務器端的程序。開啟服務端程序后,會在eclipse環(huán)境下方的控制臺里顯示如下的內容:The Server is start: ServerSocketaddr=/,port=0,localport=3333在這里,由于ServerSocket對象并沒監(jiān)聽到客戶端的請求,所以addr和后面的port值都是初始值。第二步,按同樣的方法,打開ClientCode.java程序,啟動客戶端。啟動以后,將在客戶端的控制臺里看到如下的信息:socket = Socketad

16、dr=localhost/,port=3333,localport=1326Hello Server,I am Mikeclose the Client socket and the io.從中可以看到,在第一行里,顯示客戶端Socket對象連接的IP地址和端口號,在第二行里,可以到到客戶端向服務器端發(fā)送的字符串,而在第三行里,可以看到通訊結束后,客戶端關閉連接Socket和IO對象的提示語句。第三步,在eclipse下方的控制臺里,切換到ServerCode服務端的控制臺提示信息里,我們可以看到服務器端在接收到客戶端連接請求后的響應信息。響應的信息如下所示: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.其中,第一行是啟動服務器程序后顯示的信息。在第二行里,顯示從客戶端發(fā)送的連接請求的各項參數(shù)。在第三行里,顯示了從客戶端發(fā)送過來的字符串。在第四行里,顯示了關閉服務器

18、端ServerSocket和IO對象的提示信息。從中我們可以看出在服務器端里accept阻塞和繼續(xù)運行的這個過程。通過上述的操作,我們可以詳細地觀察到C/S通訊的全部流程,請大家務必要注意:一定要先開啟服務器端的程序再開啟客戶端,如果這個步驟做反的話,客戶端程序會應找不到服務器端而報異常。2使用套接字連接多個客戶機(多線程)在7.1的代碼里,客戶端和服務器之間只有一個通訊線程,所以它們之間只有一條Socket信道。如果我們在通過程序里引入多線程的機制,可讓一個服務器端同時監(jiān)聽并接收多個客戶端的請求,并同步地為它們提供通訊服務?;诙嗑€程的通訊方式,將大大地提高服務器端的利用效率,并能使服務器端

19、能具備完善的服務功能。2.1開發(fā)服務端代碼我們可以按以下的步驟開發(fā)基于多線程的服務器端的代碼。第一步,在3.2里創(chuàng)建的“TCPSocket”項目里,新建一個名為ThreadServer.java的代碼文件,創(chuàng)建文件的方式大家可以參照3.2部分的描述。首先編寫package和import部分的代碼,用來打包和引入包文件,如下所示:package tcp;import java.io.*;import .*;第二步,由于我們在服務器端引入線程機制,所以我們要編寫線程代碼的主體執(zhí)行類ServerThreadCode,這個類的代碼如下所示:class ServerThreadCode

20、extends Thread /客戶端的socket private Socket clientSocket; /IO句柄 private BufferedReader sin; private PrintWriter sout; /默認的構造函數(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)聽通訊內容 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(); 這個類的業(yè)務邏輯說明如下:1. 這個類通過繼承Thread類來

23、實現(xiàn)線程的功能,也就是說,在其中的run方法里,定義了該線程啟動后要執(zhí)行的業(yè)務動作。2. 這個類提供了兩種類型的重載函數(shù)。在參數(shù)類型為Socket的構造函數(shù)里,通過參數(shù),初始化了本類里的Socket對象,同時實例化了兩類IO對象。在此基礎上,通過start方法,啟動定義在run方法內的本線程的業(yè)務邏輯。3. 在定義線程主體動作的run方法里,通過一個for(;)類型的循環(huán),根據(jù)IO句柄,讀取從Socket信道上傳輸過來的客戶端發(fā)送的通訊信息。如果得到的信息為“byebye”,則表明本次通訊結束,退出for循環(huán)。4. catch從句將處理在try語句里遇到的IO錯誤等異常,而在finally從句

24、里,將在通訊結束后關閉客戶端的Socket句柄。上述的線程主體代碼將會在ThreadServer類里被調用。第三步,編寫服務器端的主體類ThreadServer,代碼如下所示:public class ThreadServer /端口號 static final int portNo = 3333; public static void main(String args) throws IOException /服務器端的socket ServerSocket s = new ServerSocket(portNo); System.out.println(The Server is star

25、t: + s); try for(;) /阻塞,直到有客戶端連接 Socket socket = s.accept(); /通過構造函數(shù),啟動線程 new ServerThreadCode(socket); finally s.close(); 這段代碼的主要業(yè)務邏輯說明如下:1. 首先定義了通訊所用的端口號,為3333。2. 在main函數(shù)里,根據(jù)端口號,創(chuàng)建一個ServerSocket類型的服務器端的Socket,用來同客戶端通訊。3. 在for(;)的循環(huán)里,調用accept方法,監(jiān)聽從客戶端請求過來的socket,請注意這里又是一個阻塞。當客戶端有請求過來時,將通過ServerThre

26、adCode的構造函數(shù),創(chuàng)建一個線程類,用來接收客戶端發(fā)送來的字符串。在這里我們可以再一次觀察ServerThreadCode類,在其中,這個類通過構造函數(shù)里的start方法,開啟run方法,而在run方法里,是通過sin對象來接收字符串,通過sout對象來輸出。4. 在finally從句里,關閉服務器端的Socket,從而結束本次通訊。2.2開發(fā)客戶端代碼我們可以按以下的步驟,編寫的基于多線程的客戶端代碼。第一步,在“TCPSocket”項目里,新建一個名為ThreadClient.java的代碼文件。同樣是編寫package和import部分的代碼,用來打包和引入包文件,如下所示:pack

27、age tcp;import .*;import java.io.*;第二步,編寫線程執(zhí)行主體的ClientThreadCode類,同樣,這個類通過繼承Thread來實現(xiàn)線程的功能。class ClientThreadCode extends Thread /客戶端的socket private Socket socket; /線程統(tǒng)計數(shù),用來給線程編號 private static int cnt = 0; private int clientId = cnt+; private BufferedReader in; private PrintWriter out; /構造函

28、數(shù) public ClientThreadCode(InetAddress addr) try socket = new Socket(addr, 3333); catch(IOException e) e.printStackTrace(); /實例化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)異常,關閉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(); 這個類的主要業(yè)務邏輯是:1. 在構造函數(shù)里,通過參數(shù)類型為InetAddress類型參數(shù)和3333,初始化了本類里的Socket對象,隨后實例化了兩類IO對象,并通過start方法,啟動定義在run方法內的本線程的業(yè)務邏輯。2. 在定義線程主體動作的run方法里,通過IO句柄,向Socket信道上傳輸本客戶端的ID號,發(fā)送完畢后,傳輸”byebye”字符串,向服務器端表示本線程的通訊結束。3. 同樣地,catch從句將處理在try

31、語句里遇到的IO錯誤等異常,而在finally從句里,將在通訊結束后關閉客戶端的Socket句柄。第三步,編寫客戶端的主體代碼,在這段代碼里,將通過for循環(huán),根據(jù)指定的待創(chuàng)建的線程數(shù)量,通過ClientThreadCode的構造函數(shù),創(chuàng)建若干個客戶端線程,同步地和服務器端通訊。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í)行以后,在客戶端將會有3個通訊線程,每個線程首先將先向服務器端發(fā)送Hello Server,My id is 的字符串,然后發(fā)送”byebye”,終止該線程的通訊。2.3運行效果演示接下來,我們來觀察一下基于多線程的C/S架構的運行效果。第一步,我們先要啟動服務器端的ThreadServer代碼,啟動后,在控制臺里會出現(xiàn)如下的提示信息:The Server is start: ServerSocketaddr=

33、/,port=0,localport=3333上述的提示信息里,我們同樣可以看到,服務器在開啟服務后,會阻塞在accept這里,直到有客戶端請求過來。第二步,我們在啟動完服務器后,運行客戶端的ThreadClient.java代碼,運行后,我們觀察服務器端的控制臺,會出現(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.其中,第一行是原來就有,在后面的幾行里,首先將會輸出了從客戶端過來的線程請

35、求信息,比如In Server reveived the info: Hello Server,My id is 0接下來則會顯示關閉Server端的IO和Socket的提示信息。這里,請大家注意,由于線程運行的不確定性,從第二行開始的打印輸出語句的次序是不確定的。但是,不論輸出語句的次序如何變化,我們都可以從中看到,客戶端有三個線程請求過來,并且,服務器端在處理完請求后,會關閉Socker和IO。第三步,當我們運行完ThreadClient.java的代碼后,并切換到ThreadClient.java的控制臺,我們可以看到如下的輸出:Hello Server,My id is 0Hello

36、Server,My id is 2Hello Server,My id is 1這說明在客戶端開啟了3個線程,并利用這3個線程,向服務器端發(fā)送字符串。而在服務器端,用accept方法分別監(jiān)聽到了這3個線程,并與之對應地也開了3個線程與之通訊。3UDP協(xié)議與傳輸數(shù)據(jù)報文UDP協(xié)議一般應用在 “群發(fā)信息”的場合,所以它更可以利用多線程的機制,實現(xiàn)多信息的同步發(fā)送。為了改善代碼的架構,我們更可以把一些業(yè)務邏輯的動作抽象成方法,并封裝成類,這樣,基于UDP功能的類就可以在其它應用項目里被輕易地重用。3.1開發(fā)客戶端代碼如果我們把客戶端的所有代碼都寫在一個文件中,那么代碼的功能很有可能都聚集在一個方法力

37、,代碼的可維護性將會變得很差。所以我們專門設計了ClientBean類,在其中封裝了客戶端通訊的一些功能方法,在此基礎上,通過UDPClient.java文件,實現(xiàn)UDP客戶端的功能。另外,在這里以及以后的代碼里,我們不再詳細講述用Eclipse開發(fā)和運行Java程序的方法,而是重點講述Java代碼的業(yè)務邏輯和主要工作流程。首先,我們可以按如下的步驟,設計ClientBean這個類。通過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 ;/服務器端的端口號private int server

39、port;/通訊內容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;在上述的代碼里,我們定義了描述用來實現(xiàn)UDP通訊的DatagramSocket類型對象ds,描述客戶端和服務器端的端口號clientport和serverport,用于描述通訊信息的buffer和content對象,其中,buffer對象是byte數(shù)組類型的,可通過UDP的數(shù)據(jù)報文傳輸,而content是String類型的,在應用層面表示用戶之間的通訊內容,另外還定義了InetAddress類型的ia變量,用來封裝通訊地址信息。

42、在隨后定義的一系列get和set方法里,給出了設置和獲取上述變量的方法。第三,編寫該類的構造函數(shù),代碼如下所示。public ClientBean() throws SocketException, UnknownHostException buffer = new byte1024; clientport = 1985; serverport = 1986; content = ; ds = new DatagramSocket(clientport); ia = InetAddress.getByName(localhost);在這個構造函數(shù)里,我們給各變量賦予了初始值,其中分別設置了客戶

43、端和服務器端的端口號分別為1985和1985,設置了通訊連接地址為本地,并根據(jù)客戶端的端口號初始化了DatagramSocket對象。當程序員初始化ClientBean類時,這段構造函數(shù)會自動執(zhí)行,完成設置通訊各參數(shù)等工作。第四,編寫向服務器端發(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ù)報文,即DatagramPacket對象,并通過調用DatagramSocket類型對象的send方法,發(fā)送該UDP報文??v觀ClientBean類,我們可以發(fā)現(xiàn)在其中封裝了諸如通訊端口、通訊內容和通訊報文等對象以及以UDP方式發(fā)送信息的sendToServer方法。所以,在UDPClient類里,可以直接調用其中的接口,方便地實現(xiàn)通訊功能。其次,我們可以按如下的步驟,設計UDPClient這個類。第一步,通過import語句,引入所用到的類庫,代碼如下所示。import java.io.BufferedReader;impor

45、t java.io.IOException;import java.io.InputStreamReader;第二步,編寫線程相關的代碼。由于我們要在UDP客戶端里通過多線程的機制,同時開多個客戶端,向服務器端發(fā)送通訊內容,所以我們的UDPClient類必須要實現(xiàn)Runnable接口,并在其中覆蓋掉Runnable接口里的run方法。定義類和實現(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類里封裝的方法,設置了content內容,并通過了sentToServer方法,將content內容以數(shù)據(jù)報文的形式發(fā)送到服務器端。一旦線程被開啟,系統(tǒng)會自動執(zhí)行定義在run方法里的動作。第三步,編寫主方法。在步驟(2)里的/main方法注釋的位置,我們可以插入UDPC

溫馨提示

  • 1. 本站所有資源如無特殊說明,都需要本地電腦安裝OFFICE2007和PDF閱讀器。圖紙軟件為CAD,CAXA,PROE,UG,SolidWorks等.壓縮文件請下載最新的WinRAR軟件解壓。
  • 2. 本站的文檔不包含任何第三方提供的附件圖紙等,如果需要附件,請聯(lián)系上傳者。文件的所有權益歸上傳用戶所有。
  • 3. 本站RAR壓縮包中若帶圖紙,網(wǎng)頁內容里面會有圖紙預覽,若沒有圖紙預覽就沒有圖紙。
  • 4. 未經(jīng)權益所有人同意不得將文件中的內容挪作商業(yè)或盈利用途。
  • 5. 人人文庫網(wǎng)僅提供信息存儲空間,僅對用戶上傳內容的表現(xiàn)方式做保護處理,對用戶上傳分享的文檔內容本身不做任何修改或編輯,并不能對任何下載內容負責。
  • 6. 下載文件中如有侵權或不適當內容,請與我們聯(lián)系,我們立即糾正。
  • 7. 本站不保證下載資源的準確性、安全性和完整性, 同時也不承擔用戶因使用這些下載資源對自己和他人造成任何形式的傷害或損失。

評論

0/150

提交評論