490 likes | 816 Views
網路程式設計 Network Programming Ch.5 JAVA 網路套件. 陳冠中 國立高雄應用科技大學. 章節大綱. 5-1 位址類別. 5-4 URL 類別. 5-2 SocketAddress 類別. 5-5 URLConnection 類別. 5-3 Socket 類別. 備註:可依進度點選小節. 5-1 位址類別. Java 網路相關的類別都配置於 java.net 套件中 利用這些 JDK 所提供的類別,開發人員得以不用花時間實作或撰寫基礎的網路類別,就可以快速設計出 具有網路通訊功能 的程式。
E N D
網路程式設計Network ProgrammingCh.5 JAVA網路套件 陳冠中 國立高雄應用科技大學 2012 網路程式設計
章節大綱 5-1 位址類別 5-4URL類別 5-2SocketAddress類別 5-5URLConnection類別 5-3Socket類別 備註:可依進度點選小節
5-1 位址類別 • Java網路相關的類別都配置於java.net套件中 • 利用這些JDK所提供的類別,開發人員得以不用花時間實作或撰寫基礎的網路類別,就可以快速設計出具有網路通訊功能的程式。 • 有效率地使用這些類別是網路程式設計重要的基礎 • 本章的範例將實作如何連線至網站的程式 2012 網路程式設計
5-1 位址類別 • java.net.InetAddress類別 • Internet Address用來表示主機名稱或IP位址 • InetAddress類別可用在TCP與UDP網路程式設計 • 類別方法getByName(String host)會利用DNS主機查詢到主機名稱字串資料所註冊的IP位址: InetAddress addr= InetAddress.getByName("java.sun.com"); System.out.println(addr); ▌印出addr物件的結果為: java.sun.com/192.9.162.55 2012 網路程式設計
5-1 位址類別 • java.net.InetAddress類別 • 類別方法getLocalHost()可得到本機(localhost)的網址物件如下: • InetAddresslocal = InetAddress.getLocalHost(); • System.out.println(local); ▌印出local物件的結果為(每台主機執行結果不盡相同): core2/192.168.1.10 2012 網路程式設計
5-1 位址類別 • InetAddress • InetAddress類別並不以建構子的方式產生物件,而是使用它的「靜態方法(static methods)」,以下是較常使用的方法: • 1. static InetAddress getByName(String host) • 給予一個主機名稱host字串,將回傳一個經DNS查詢得到的位址物件(包括主機名稱與IP位址),如下範例: InetAddress addr= InetAddress.getByName("java.sun.com"); System.out.println(addr); ▌執行結果 java.sun.com/72.5.124.55 2012 網路程式設計
5-1 位址類別 • InetAddress • 2. static InetAddress getByAddress(byte[] addr) • 傳入一個以byte陣列表示的IP位址,得到一個位址物件。 • byte[] b = { 61 , 64 , 12 ,1 }; • InetAddressaddr = InetAddress.getByAddress(b); • System.out.println(addr); ▌執行結果 /61.64.12.1 2012 網路程式設計
5-1 位址類別 • InetAddress • 3. static InetAddress getLocalHost() • 取得本機的位址物件,如下: • InetAddressaddr= InetAddress.getLocalHost(); • System.out.println(addr); ▌執行結果 core2/169.254.4.238 2012 網路程式設計
5-1 位址類別 • InetAddress • 4. static InetAddress[] getAllByName(String host) • 取得主機名稱host字串所對應的所有IP位址物件,回傳位址物件的陣列,如果本機有多個IP位址,可以由此方法取得所有IP位址物件 • InetAddressaddr[] = InetAddress.getAllByName("shaoye-PC "); • for (inti=0; i<addr.length; i++){ • System.out.println(addr[i]);} 須改成實際主機名稱或FQDN www.yahoo.com.tw來說,yahoo.com.tw是Domain Name, 而www是Host Name ▌執行結果 ore2/169.254.4.238 core2/192.168.1.10 core2/192.168.174.1 core2/192.168.83.1 core2/fe80:0:0:0:e414:6431:bf2d:99b8%11 core2/fe80:0:0:0:14a6:270b:4ae5:8872%18 core2/fe80:0:0:0:2966:8bde:3f65:49ae%19 core2/fe80:0:0:0:886:d53a:7968:4ee%29 Yahoo!奇摩的FQDN: www.yahoo.com.tw 2012 網路程式設計
5-1 位址類別 • 取得本機的網路介面-NetworkInterface • JDK第6版內的java.net.NetworkInterface類別提供更詳細的網路卡資訊 • 網路卡eth0、eth1的方式命名 • 利用NetworkInterface類別的靜態方法可以得到網路介面的物件 2012 網路程式設計
5-1 位址類別 • 取得本機的網路介面-NetworkInterface • 1. static NetworkInterface getByName(String name) • 傳入一個網路介面名稱,可得到符合該名稱的物件,若無符合的名稱,則回傳null值,如下: • NetworkInterface eth = NetworkInterface.getByName("eth0"); • System.out.println(eth.getName()); • System.out.println(eth.getDisplayName()); ▌執行結果 eth0 Marvell Yukon 88E8001/8003/8010 PCI Gigabit Ethernet Controller 2012 網路程式設計
5-1 位址類別 • 取得本機的網路介面-NetworkInterface • 2. static Enumeration<NetworkInterface> getNetworkInterfaces() • 若想列出主機上所有的網路介面,可使用本方法得到列舉集合,以下範例程式可列出所有的網路介面的名稱與其是否啟用: • Enumeration<NetworkInterface> ifs = NetworkInterface.getNetworkInterfaces(); • while (ifs.hasMoreElements()){ • NetworkInterface ni = ifs.nextElement(); • System.out.println(ni.getName()); • System.out.println(" 是否正啟用:"+ni.isUp()); • } 2012 網路程式設計
5-1 位址類別 • ▌執行結果 • lo • 是否正啟用:true • net0 • 是否正啟用:false • net1 • 是否正啟用:false • net2 • 是否正啟用:false • net3 • 是否正啟用:false • ppp0 • 是否正啟用:false • eth0 • 是否正啟用:false • eth1 • 是否正啟用:false • eth2 • 是否正啟用:false 2012 網路程式設計
5-1 位址類別 • 常用的方法有: • String getName():取得網路介面的名稱字串,通常有eth0,eth1或 net1,net2或ppp1,ppp2等。 • String getDisplayName():取得網路介面的易讀名稱字串,一般人較容易瞭解的名稱,如網路介面的品牌與型號。 • boolean isUp():回傳布林值,以辨認該網路介面是否處於啟用狀態。 • int getMTU():得到該網路介面的「最大傳輸單位值(MTU)」。 • boolean isVirtual():回傳該網路介面是否為一個虛擬裝置,又稱為子介面(subinterface)。 • getSubInterfaces():得到該網路介面下的所有虛擬裝置。 2012 網路程式設計
5-2SocketAddress類別 • SocketAddress抽象類別定義了一個未綁定任何通訊協定的規格,讓其他類別繼承。 • 如TCP/IP協定所使用的InetSocketAddress類別,它是代表一個網址,而一個網址內有IP位址與埠號(port)兩項資訊。 2012 網路程式設計
5-3Socket類別 • java.net.Socket類別常用來建立Client/Server型的連線 • 建立連線後就可利用輸出入串流物件進行資料傳輸 • TCP程式設計是先利用Socket類別,再利用串流物件 2012 網路程式設計
5-3Socket類別 • 建立Socket物件 • 此例必須啟動本機telnet service才能連線至主機 • 最常使用的建構子是給予主機名稱字串與遠端主機的埠號(port),由於主機名稱不一定正確,或是遠端主機可能有無法連線的情況,因此使用Socket建構子時,必須為其處理UnknownHostException與IOException例外,當連線失敗時將會顯示「主機連線失敗」,如下以try...catch處理之: • try { • Socket ptt = new Socket("localhost ", 23); • }catch (UnknownHostException ex){ • System.out.println("主機連線失敗"); • }catch (IOException ex){ • System.out.println("傳輸失敗"); • } 2012 網路程式設計
如何啟動windows XP telnet service • 1. 在 [控制台] 中,連按兩下 [系統管理工具]。2. 按兩下 [服務]。3. 按兩下 [Telnet]。4. [啟動類型] 選擇 [手動]。5. 按一下 [套用]。6. 按一下 [啟動]。7. 按一下 [確定]。 2012 網路程式設計
如何啟動windows 7 telnet service • Step 1. 控制台程式和功能(左邊)開啟或關閉Windows功能將Telnet用戶端 及 Telnet伺服端 啟動(勾選) • Step 2.“開始”“運行”,輸入servcies.msc打開服務管理器。找到並雙擊Telnet服務項,設置其啟動方式為“手動”(更安全,只在需要的時候才啟用) 2012 網路程式設計
5-3Socket類別 • 建立Socket物件 • 當程式執行到Socket建構子時,會直接嘗試與遠端主機的埠號建立TCP連線。Socket類別建構子還可以使用InetAddress物件與遠端主機建立連線,程式範例如下: • try { • InetAddress addr = InetAddress.getByName("localhost"); • Socket ptt = new Socket(addr, 23); • System.out.println(“主機連線成功!!"); • }catch (UnknownHostException ex){ • System.out.println("主機連線失敗"); • } catch (IOException ex){ • System.out.println("傳輸失敗"); • } 2012 網路程式設計
5-3Socket類別 • 建立Socket物件 • Socket類別中有方法會使用到SocketAddress物件,都是有關本地與遠端位址與埠號,例如: • public SocketAddress getLocalSocketAddress():取得本地的SocketAddress物件。 • public SocketAddress getRemoteSocketAddress():取得連線遠端的SocketAddress物件。 • public void bind(SocketAddress bindpoint):將Socket物件綁定一個本地位址。 • public void connect(SocketAddress endpoint):使用SocketAddress物件內的資訊,連線至其指定的遠端主機 • public void connect(SocketAddress endpoint, int timeout):使用SocketAddress物件內的資訊,連線至其指定的遠端主機,並訂定連線超過某一時間無法成功時,即告失敗。timeout值以毫秒(千分之一秒)為單位。 2012 網路程式設計
5-3Socket類別 • 本範例使用上述的幾個方法,由local主機的port 2222出發的連線,連至remote主機ptt.cc的port 23。 • 由於使用了timeout值很短(5亳秒),因此本範例執行後會throw一個java.net.SocketTimeoutException例外(5亳秒5000亳秒): 01 package com.ch05; 02 03 import java.io.IOException; 04 import java.io.net.InetSocketAddress; 05 import java.net.Socket; 06 07 public class ch5Practice{ 08 public static void main(String[] args) throws IOException { 09 Socket socket = new Socket(); 10 InetSocketAddress local = new InetSocketAddress(2222); 11 InetSocketAddress ad = new InetSocketAddress(“ptt.cc”,443); 12 socket.bind(local); 13 System.out.println(“本地埠號:“+socket.getLocalPort()); 14 socket.connect(ad,5); 15 } 16 } 2012 網路程式設計
5-3-2Socket的方法 • Socket的方法 • public InetAddress getInetAddress()取得連線至遠端的位址物件。 • public int getPort()取得連線至遠端的埠號值。 • public InetAddress getLocalAddress()取得此連線在本地端的位址物件。 • public int getLocalPort()取得此連線在本地端的埠號值。 • public InputStream getInputStream()取得此連線的輸入資料流物件,以供後續讀取遠端傳送來的資料。 • public OutputStream getOutputStream()取得此連線的輸出資料流物件,以供後續傳送資料至遠端主機。 • public void close()關閉此連線。 2012 網路程式設計
5-3-2Socket的方法 • 01 package com.ch05; • 02 • 03 import java.io.IOException; • 06 import java.net.Socket; • 07 import java.net.UnknownHostException; • 08 • 09 public class SimpleSocket2 { • public static void main(String[] args) throws UnknowHostException, IOException { • Socket socket = new Socket(“www.google.com”,80); • 12 System.out.println(“本地位址:“ + socket.getLocalAddress()); • 13 System.out.println(“本地埠號:“ + socket.getLocalPort()); • 14 System.out.println(“遠端位址:“ + socket.getInetAddress()); • 15 System.out.println(“遠端埠號:“ + socket.getPort()); • 16 } • 17 } 2012 網路程式設計
5-3Socket類別 • 取得輸出入串流 • 當Socket物件成功建立後,客戶端(程式)與伺服器端(遠端主機)可開始進行資料的傳輸,此時要利用java.io套件庫內的串流類別(Stream),如簡單的InputStream/OutputStream或支援亞洲字元的Reader/Writer類別。 • Socket類別可比喻為插頭,而串流類則是由插頭衍生出來的電線,如下圖: 2012 網路程式設計
5-3Socket類別 2012 網路程式設計
5-3Socket類別 • 01 package com.ch05; • 02 • 03 import java.io.IOException; • 04 import java.io.InputStream; • 05 import java.io.OutputStream; • 06 import java.net.Socket; • 07 import java.net.UnknownHostException; • 08 • 09 public class SimpleTCP { • 10 public static void main(String[] args) { • 11 try { • 12 Socket ptt = new Socket("ptt.cc",443); • 13 InputStream in = ptt.getInputStream(); • OutputStream out = ptt.getOutputStream(); • System.out.println(“主機連線成功"); • 16 } catch (UnknownHostException e) { • 17 System.out.println("主機連線失敗"); • 18 } catch (IOException e) { • 19 System.out.println("傳輸失敗"); • 20 } • 21 } • 22 } 由Socket物件取得串流物件的方法為getInputStream與getInputStream 2012 網路程式設計
5-3Socket類別 • 5-3-4傳輸資料 • 取得輸出入串流物件後,便可利用串流物件提供的方法,進行資料的接收與傳送 • 資料接收以InputStream的read()方法 • 資料傳送以OutputStream的write()方法將資料傳送至遠端主機 • 接收遠端主機傳來一個byte值,收到的資料以整數int的方式: • 傳送一個byte值,以整數int資料型態傳送出去,並利用flush()方去確認資料不會留存於本地端的緩衝區,送達到遠端主機: • Int data = in.read(); • out.write(65); • out.flush(); 2012 網路程式設計
5-3Socket類別 • 關閉連線 • 當程式執行至main方法的最後時,會結束整個程式,並自動將程式中使用到的變數、物件等資源釋出,但讀者在設計網路連線相關程式時,最好利用串流物件與通道物件的close()方法,主動地關閉其資源並斷線,以免遠端主機花費多餘的資源在等待斷線訊號。 • 呼叫InputStream物件in的方法close(),關閉輸入串流: • 呼叫OutSteam物件out的方法close(),關閉輸出串流: • 呼叫Socket物件ss的方法close(),關閉本機與遠端主機的連線: • In.close(); • out.close(); • ss.close(); 2012 網路程式設計
5-3Socket類別 • Telnet程式範例 • 利用連線至PTT BBS,取得遠端主機傳輸資料為例,程式中在連線成功後,以for迴圈從BBS站(遠端主機)讀取10個位元組,並印出資料: Socket ptt = new Socket("ptt.cc",23); InputStream in = ptt.getInputStream(); OutputStream out = ptt.getOutputStream(); int data = 0; for (int i=0; i<10; i++){ data = in.read(); System.out.print(data + " "); } in.close(); out.close(); ptt.close(); ▌執行結果 32 32 32 32 32 163 187 32 32 32 2012 網路程式設計
5-3Socket類別 • Telnet程式範例 • 上述執行的結果得到遠端主機先傳來5個空白(ASCII碼為空白),再收到一個Big5碼中文字(163 187),再收到3個空白。其實遠端主機後續仍有資料等待傳送至本機,但本例只用for迴圈讀到10個位元組就斷線了。 • telnet程式執行 telnet ppt.cc 2012 網路程式設計
5-4URL類別 • URL(Universal Resource Locator)稱為網址 • URL是用來上找到(定位)一個特定的網路資源,也是一個表示特定網際網路資源的國際標準 通訊協定://伺服器位址或名稱[:埠號]/路徑/檔名 • 例如:http://www.ibm.com/docs/abc.txt 2012 網路程式設計
5-4URL類別 • URL標準制定了以下常用的通訊協定 • http • 網頁通訊協定 • https • 加密傳送的網頁通訊協定 • ftp • 檔案傳輸協定 • file • 定位本地電腦上的檔案 2012 網路程式設計
5-4URL類別 • URL類別的建構子並不複雜,目的是要將一串包含資訊的字串轉換為URL物件,由於使用者傳入的網址並不一定正確地定位到特定資源,使用URL類別的建構子時皆需要處理例外(Malformed URLException),初學時可以在使用建構子的方法定義時,直接以throws關鍵字將該例外拋出。 2012 網路程式設計
5-4URL類別 • URL的建構子 • 1.URL(String spec) • 傳入一個URL字串,並產生一個URL物件,例如: • 2.URL(String proto, String host, int port, String file) • 將URL的四個要項分開為字串與整數,傳入URL類別建構子當成參數,並產生一個URL物件,例如: • 3.URL(String proto, String host, String file) • 使用預設的埠別,而需不傳入埠號參數,在URL物件中埠號的預設值為-1,代表使用該協定的預設埠號,若協定為ftp則預設使用21埠號,若協定為http則使用80埠號。 • URL url = new URL("http://snpy.org/net/index.html"); • URL url = new URL("http", "snpy.org", 80, "/net/index.html"); 2012 網路程式設計
5-4URL類別 • URL類別的方法 • String getProtocol():取得URL物件內的協定,回傳值為字串格式。 • String getHost():取得URL物件內的主機資訊,回傳值為字串格式。 • String getPort():取得URL物件內的埠號值,回傳值為整數格式。 • String getPath():取得URL物件內的目錄資訊(包括檔案),回傳值為字串格式。 • String getFile():取得URL物件內的檔案名稱(包括目錄),回傳值為字串格式。 2012 網路程式設計
5-4URL類別 • URL類別的方法 • URLConnection openConnection():依照URL物件中的欄位資訊開啟該資源,並回傳與該資源的URLConnection連線物件,後續可進行資料的讀取與傳送。URLConnection類別將於下一節內容中詳述。 • InputStream openStream():依照URL物件中的欄位資訊開啟該資源,回傳連線後的輸入資源流InputStream,可快速讀取遠端資源中的資料。 2012 網路程式設計
5-4URL類別 2012 網路程式設計
5-5URLConnection類別 • URLConnection類別代表與該網際網路資源的實質連線 • 由實質連線中又可以得到輸入或輸出的資料流物件 • URL可以比喻為一張寫著住址的紙張,而URLConnection則是依照紙張上的資訊,建立起本機與遠端資源的橋樑 2012 網路程式設計
5-5URLConnection類別 • 取得網際網路資源 • 想要連線到下列網址,並取得該網址的資料: http://j.snpy.org/net/index.html 1. 產生URL物件 2. 取得URLConnection連線物件 3. 與該資源建立實質連線 4. 取得輸入資料流物件 URL url = new URL("http://j.snpy.org/net/index.html"); URLConnection conn = url.openConnection(); conn.connect(); InputStream in = conn.getInputStream(); 2012 網路程式設計
5-5URLConnection類別 • 取得網際網路資源 5. 以迴圈取得所有資料 6. 關閉資料流物件 • int data = in.read(); • while (data!=-1){ • System.out.print((char)data); • data = in.read(); • } in.close(); 2012 網路程式設計
5-5URLConnection類別 • 由於上例使用以byte為單位的串流物件(InputStream),若網際網路資源中含有中文時,則會將雙位元或UTF-8的資源拆開處理,而造成讀取資料不正確的亂碼,例如以下的執行結果: 2012 網路程式設計
5-5URLConnection類別 因此,必須要知道遠端資源的內容編碼方式後,才能夠以特定編碼格式處理資料而得到正確的資料。 • 標頭(Header)資訊 • 本節使用的URL內容是網頁協定,因此,要先取得HTTP協定的標頭(Header)資訊才能得知遠端資源的編碼格式 • 先利用URLConnection的方法getContentType()取得遠端資源的「內文(Content)」格式 得到: text/html; charset=UTF-8 • String type = conn.getContentType(); • System.out.println("內文格式:"+type); 2012 網路程式設計
5-5URLConnection類別 • 利用字串類別的方法lastIndexOf(“=“)找到最後一個等號,再以字串方法substring()取得編碼字串(“UTF-8“); • 之後便可利用Java輸出入套件的Reader類別讀取遠端資源並完成轉碼,得到正確的中文內容,完整程式碼: 2012 網路程式設計
5-5URLConnection類別 • 執行結果,正確得到”這是測試網頁”內文資料。 2012 網路程式設計
Any Question? 2012 網路程式設計