Java學習筆記—第十二章 Java網絡編程入門

第十二章  Java網絡編程入門

  1. Java提供的三大類網絡功能:

    (1)URL和URLConnection:三大類中最高級的一種,通過URL網絡資源表達方式,可以很容易確定網絡上數據的位置。利用URL的表示和建立,Java程序可以直接讀入網絡上所放的數據,或把自己的數據傳送到網絡的另一端。

    (2)Socket:又稱“套接字”,用於描述IP地址和端口(在Internet中,網絡中的每臺主機都有一個唯一的IP地址,而每臺主機又通過提供多個不同端口來提供多種服務)。在客戶/服務器網絡中,當客戶機中運行的應用程序(如網頁瀏覽器)需要訪問網絡中的服務器時,客戶機會被臨時分配一個Socket,然後它會通過服務器的Socket向服務器發出請求。簡而言之,網絡中的數據的發送和接收都是通過Socket來完成的,Socket就像一個文件句柄(讀寫文件時的一個唯一的順序號),用戶可以通過讀寫Socket來完成客戶機、服務器之間的通信。

    (3)Datagram:三大類中最低級的一種。其他網絡數據傳送方式都假想在程序執行時建立一條安全穩定的通道,但是以Datagram方式傳送數據時,只是把數據的目的地記錄在數據包中,然後就直接放在網絡上進行傳輸。系統不保證數據一定能安全送達,也不能確定什麼時候可以送到。也就是說,Datagram不能保證傳送質量。

  2. 瞭解Java網絡編程基礎知識

    (1)網絡編程中有兩個主要問題:如何準確定位網絡上的一臺或多臺主機,以及找到主機後如何可靠地、高效地進行數據傳輸。在TCP/IP網絡協議中,IP地址可以唯一確定Internet上的一臺主機,而TCP則提供可靠的數據傳輸機制。

    (2)TCP/IP協議(傳輸控制協議/因特網互聯協議  網絡通信協議)

    TCP/IP協議是Transmission Control Protocol/Internet Protocol的縮寫,是Internet最基本的協議,是供已連接因特網的計算機進行通信的通信協議。其定義了電子設備(如計算機)如何連入因特網,以及數據如何在它們之間傳輸的標準。TCP/IP協議由網絡層IP協議和傳輸層的TCP協議組成。

    計算機網絡通信劃分爲七層,自下而上分別是:物理層,數據鏈路層,網絡層,傳輸層,會話層,表示層,應用層。每一層都提供了不同的網絡協議。

    TCP/IP使用客戶端/服務器模式進行通信,且通信是點對點的,即通信是在網路中的兩臺主機之間進行的。TCP協議爲傳輸控制協議,負責聚集信息或把文件拆分成更小的包。這些包通過網絡傳送到接收端的TCP層,接收端的TCP層把包還原爲原始文件。IP協議是網際協議,負責處理每個包的地址部分,使這些包能正確到達目的地。網絡上的網關計算機根據信息的地址來進行路由選擇。即使來自同一文件的分包路由也有可能不同,但最後會在目的地匯合。

  3. TCP協議與UDP協議(傳輸層)

    (1)TCP協議:面向連接,可靠傳輸。客戶端與服務器之間必須先建立連接才能進行通信。得到一個順序的、無差錯的數據流。可以傳輸大容量數據,並確保服務器正確地接收到客戶端發送的全部數據。

    (2)UDP協議:User Datagram Protocol(用戶數據報協議),一種面向無連接,不可靠的傳輸協議。它將信息包裝成數據報進行傳輸,數據報中包含完整的源地址或目的地址。不能保證數據報是否到達目的地、到達目的地的時間以及內容的正確性。傳輸數據大小限定在64KB之內。

  4. IP地址

    Java中用InetAddress類來描述IP地址。這個類沒有公共的構造方法,但是它提供了三個用來獲得InetAddress對象的靜態方法。分別是:

    InetAddress getLocalHost():返回一個本地主機的InetAddress對象。

    InetAddress getByName(String host):返回主機名host指定的InetAddress對象。

    InetAddress[] getAllByName():對於某個多IP地址主機,可用該方法得到一個IP地址數組。

    此外,InetAddress類還提供了以下方法:

    String getHostAddress();返回IP地址字符串。

    String getHostName();返回主機名。

    例如:

    public class InetAddressTest{

       public static void main(String[] args){

           InetAddress ia;

           ia = InetAddress.getLocalHost();   //獲得本地主機的InetAddress對象

           String localHostAddress = ia.getHostAddress(); //獲得本地主機IP地址

           String localHostName = ia.getHostName()  //獲得本地主機名

           ia = InetAddress.getByName("www.baidu.com");  //獲得百度網主機的InetAddress對象

           String bdHostAddress = ia.getHostAddress();  //獲取百度網主機地址

           String bdHostName = ia.getHostName();        //獲取百度網主機名

       }

    }

  5. 端口

    端口是爲了在一臺主機上提供更多的網絡資源而採取的一種手段。只有通過IP地址和端口號才能唯一地確定網絡通信中的進程。端口用端口號來標記,端口號用0~65535的整數表示。

  6. 使用URL訪問網絡資源

    (1)URL:Uniform Resource Locator(統一資源定位符),對Internet資源的一個引用。大多數情況下,資源表示爲一個文件,如一個HTML文檔,一個圖像文件,或一個聲音片段等。因此,可以將URL理解爲一個Internet資源地址。通用格式如下:

    <PROTOCOL>://<HOSTNAME:PORT>/<PATH>/<FILE>

    PROTOCOL表示Internet協議,常用的有HTTP、FTP、SMTP等。HOSTNAME表示資源所在的Internet主機名。主機名和IP地址是一一對應的,通過域名解析可以由主機名得到IP地址。PORT表示端口號,每一個Internet協議都有自己對應的端口號。PATH和FILE分別表示資源的路徑名和文件名。

    (2)創建URL對象

    Java中可以使用URL類訪問Internet資源。URL類的構造方法如下:

    a. URL(String spec):使用表示URL地址的字符串spec創建URL對象。例如:

    URL url = new URL("http://www.sina.com.cn");

    b. URL(URL baseURL,String relativeURL):使用絕對地址baseURL與相對地址relativeURL創建URL對象。例如:

    URL baseURL = new URL("http://www.base.edu.cn");

    URL url = new URL(baseURL,"/library/library.htm");

    c. URL(String protocol,String hostName,int port,String fileName):使用網絡協議protocol、主機名hostName、端口號port、文件名fileName創建URL對象。例如:

    URL url = new URL("http","www.baidu.com","80","/library/library.htm"); 

    d. URL(String protocol,String hostName,String fileName):使用網絡協議protocol、主機名hostName、文件名fileName創建URL對象。例如:

    URL url = new URL("http","www.baidu.com","/library/library.htm");

    備註:URL類的構造方法會拋出非運行時異常MalformedURLException,程序需要對此進行處理。 

  7. 直接通過URL對象讀取內容

    成功建立一個URL對象後,可以調用openStream()方法從網絡資源中讀取內容。例如:

    public class OpenStreamTest{

       public static void main(String[] args){

           try{

                URL sina = new URL("http://www.sina.com.cn/");

                DataInputStream dis = new DataInputStream(sina.openStream());

                String readLine;

                while((readLine = dis.readLine())!=null){

                    System.out.print(readLine);

                }

                dis.close();

            }catch(MalformedURLException me){

                System.out.print("MalformedURLException:"+me);      

            }catch(IOException ioe){

                System.out.print("IOException:"+ioe);

            }

        }

    }

8. 建立一個URL連接並從中讀取內容

   通過URL類的openStream()方法,只能從網絡資源中讀取數據。如果想同時對數據進行讀寫操作,則必須利用URLConnection類建立一個URL連接。當與一個URL對象建立連接時,首先要通過URL對象的openConnection()方法生成URLConnection對象。URLConnection對象表示Java程序和URL對象在網絡上的通信連接。如果連接過程失敗,將會產生IOException。例如:

    public class URLConnectionTest{

        public static void main(String[] args){

            try{

                URL baidu = new URL("http://www.baidu.com/");

                URLConnection conn = baidu.openConnection();

                //創建數據輸入流

                DataInputStream dis = new DataInputStream(baidu.getInputStream);

                String inputLine;

                while((inputLine = dis.readLine())!=null){

                    System.out.print(inputLine);

                }

                dis.close();

            }catch(MalformedURLException me){

                System.out.print("MalformedURLException:"+me);

            }catch(IOException ioe){

                System.out.print("IOException:"+ioe);

            }

        }

    }

9. 使用Socket進行網絡通信

    在應用層通過傳輸層進行數據通信時,TCP或UDP協議會遇到同時爲多個應用程序進程提供併發服務的問題。多個TCP連接或多個應用程序進程可能需要通過同一個端口傳輸數據。爲了區別不同的應用程序進程或連接,計算機操作系統爲應用程序與TCP/IP協議交互提供了稱爲套接字(Socket)的接口。每個Socket由IP地址、傳輸層協議(TCP或UDP)、端口號三個參數唯一確定。

    使用Socket進行服務器/客戶端的通信時,可以分爲三個步驟:服務器監聽,客戶端請求,連接確認。

    (1)服務器監聽:服務器端Socket實時監聽某個端口是否有連接請求。

    (2)客戶端請求:指由客戶端的Socket提出連接請求,要連接的目標是服務器端的Socket。客戶端的Socket首先需要描述它要連接的服務器端的Socket,指出服務器端Socket的IP地址和端口號,然後便可以向服務器端發送連接請求。

    (3)連接確認:當服務器端的Socket監聽到或者接收到客戶端Socket的連接請求時,就響應客戶端的請求,並建立一個新的線程,然後把服務器端的Socket的描述發送給客戶端。一旦客戶端確認了此描述,一個連接便建立起來了。而服務器端Socket繼續處於監聽狀態,並接收其他客戶端Socket的連接請求。

    (4)常見的Socket主要分爲兩種:

    a. 流式Socket:一種基於TCP協議的通信,即在通信開始之前先由通信雙方確認身份並建立一條連接通道,然後通過這條通道傳輸數據。

    b. 數據報Socket:一種基於UDP協議的通信,無需通信雙方建立連接,而是直接將信息打包傳向指定的目的地。

    (5)流式Socket編程

      java.net包中定義了Socket類和ServerSocket類,它們是實現流式Socket通信的主要工具。創建Socket對象就創建了一個客戶端與服務器端的連接,而創建一個ServerSocket對象就創建了一個監聽服務。

     a. Socket類:通過構造一個Socket對象可以建立客戶端與服務器的連接。Socket類的構造方法如下:

     Socket(String host,int port)

     Socket(InetAddress address,int port)

     Socket(InetAddress address,int port,InetAddress localAddr,int localPort)

    其中,host、port和address分別表示連接主機的主機名、端口號和IP地址;locaAddr表示本地主機的IP地址;localPort表示本地主機端口號。例如:

    Socket mySocket = new Socket("www.sina.com",3000);

    備註:每一個端口號提供一種特定的服務,只有給出正確的端口,才能獲得相應的服務。0~1023的端口號爲系統保留,例如,http服務的端口號爲80,telenet服務的端口號爲23,ftp服務端口號爲21。

    創建一個新的Socket對象後,就可以使用其getInputStream()方法獲得一個InputStream流,然後可以通過InputStream對象從某個主機接收信息;而使用getOutputStream()可以獲得一個OutputStream對象,利用它可以發送信息到某個主機。例如:

    public class GetDayTime{

        public static void main(String[] args){

            try{

                Socket socket = new Socket("stdtime.gov.hk",13);

                BufferedReader br = new BufferedReader(new                                                                      InputStreamReader(socket.getInputStream()));

                String daytime = br.readLine();

                System.out.println("DayTime received:"+daytime);

                socket.close();

            }catch(IOException e){

                System.out.println("ERROR:"+e);

            }

        }

    }

    b. ServerSocket類

    ServerSocket類表示通信雙方中的服務器,它可以監聽客戶端發送的連接請求並進行處理。將服務器所監聽的端口號傳遞給ServerSocket的構造方法,就可以創建一個ServerSocket對象。ServerSocket類的構造方法如下:

    ServerSocket(int port);

    ServerSocket(int port,int count);

    其中,port表示端口號,count表示服務器所能支持的最大連接數。例如:

    ServerSocket serverSocket = new ServerSocket(5000);

    這裏指定服務器監聽的端口號是5000。當創建一個ServerSocket對象後,就可以調用accept()方法接受來自客戶端的請求。其格式爲:

    Socket socket = serverSocket.accept();

    ServerSocket對象的accept()方法會使服務器端的程序一直處於阻塞狀態,直到捕獲一個來自客戶端的請求,並返回一個Socket類的對象來處理與客戶端的通信。

    當需要結束監聽時,可以使用如下語句關閉這個ServerSocket對象:

    serverSocket.close();

    (6)數據報Socket編程

    java.net包中提供了DatagramPacket和DatagramSocket類用來支持無連接的數據報Socket通信。DatagramSocket類用於在程序之間建立傳送數據報的通信連接,DatagramPacket類則用於存儲數據報等信息。

    a. DatagramSocket類:構造方法如下:

    DatagramSocket();

    DatagramSocket(int port);

    DatagramSocket(int port,InetAddress localAddr);

    其中,port表示端口號;localAddr表示本地地址。

    DatagramSockt類構造方法會拋出非運行時異常SocketException,程序需要對此進行處理。

    b. DatagramPacket類:

    用數據報方式編寫Client/Server程序時,無論在客戶端還是服務器,都首先需要建立一個DatagramSocket對象,用來接收或發送數據報,而DatagramPacket對象是數據報傳輸的載體。構造方法如下:

    DatagramPacket(byte[] buf,int length);

    DatagramPacket(byte[] buf,int length,InetAddress address,int port);

    其中,字節數組buf中存放欲發送或接收的數據報,length表示數據報的長度,address和port表示數據報發送的目的地和主機端口號。

    在客戶端或服務器端接收數據之前,應該採用DatagramPacket類的第一種構造方法創建一個DatagramPacket對象,然後調用DatagramSocket類的receive()方法等待數據報的到來。例如:

    DatagramSocket socket = new DatagramSocket();

    DatagramPacket packet = new DatagramPacket(buf,256);

    socket.receive();

    在發送數據之前,需要使用DatagramPacekt類的第二種構造方法創建一個新的DatagramPacket對象,即要指明數據報發送的目的地址和端口號。發送數據報通過DatagramSocket類的send()方法實現。例如:    

    DatagramSocket socket = new DatagramSocket();

    DatagramPacket packet = new DatagramPacket(buf,length,address,port);

    socket.send(packet);

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章