<rt id="bn8ez"></rt>
<label id="bn8ez"></label>

  • <span id="bn8ez"></span>

    <label id="bn8ez"><meter id="bn8ez"></meter></label>

    資料整理

     

    網絡編程

       1. 什么是 TCP/ IP 協議?
       2. TCP/IP 有哪兩種傳輸協議 , 各有什么特點?
       3. 什么是 URL
       4. URL IP 地址有什么樣的關系?
       5. 什么叫套接字( Socket )?
       6. 套接字( Socket )和 TCP/IP 協議的關系?
       7. URL 和套接字( Socket )的關系?
    8.1 網絡編程基本概念,TCP/IP協議簡介

    8.1.1 網絡基礎知識

    網絡編程的目的就是指直接或間接地通過網絡協議與其他計算機進行通訊。網絡編程中有兩個主要的問題,一個是如何準確的定位網絡上一臺或多臺主機,另一個就是找到主機后如何可靠高效的進行數據傳輸。在 TCP/IP 協議中 IP 層主要負責網絡主機的定位,數據傳輸的路由,由 IP 地址可以唯一地確定 Internet 上的一臺主機。而 TCP 層則提供面向應用的可靠的或非可靠的數據傳輸機制,這是網絡編程的主要對象,一般不需要關心 IP 層是如何處理數據的。
       目前較為流行的網絡編程模型是客戶機 / 服務器( C/S )結構。即通信雙方一方作為服務器等待客戶提出請求并予以響應。客戶則在需要服務時向服務器提出申請。服務器一般作為守護進程始終運行,監聽網絡端口,一旦有客戶請求,就會啟動一個服務進程來響應該客戶,同時自己繼續監聽服務端口,使后來的客戶也能及時得到服務。

    8.1.3兩類傳輸協議:TCP;UDP
       盡管 TCP/IP 協議的名稱中只有 TCP 這個協議名,但是在 TCP/IP 的傳輸層同時存在 TCP UDP 兩個協議。

    TCP Tranfer Control Protocol 的簡稱,是一種面向連接的保證可靠傳輸的協議。 通過 TCP 協議傳輸,得到的是一個順序的無差錯的數據流。發送方和接收方的成對的兩個 socket 之間必須建立連接,以便在 TCP 協議的基礎上進行通信,當一個 socket (通常都是 server socket )等待建立連接時,另一個 socket 可以要求進行連接,一旦這兩個 socket 連接起來,它們就可以進行雙向數據傳輸,雙方都可以進行發送或接收操作。
       UDP User Datagram Protocol 的簡稱,是一種無連接的協議, 每個數據報都是一個獨立的信息,包括完整的源地址或目的地址,它在網絡上以任何可能的路徑傳往目的地,因此能否到達目的地,到達目的地的時間以及內容的正確性都是不能被保證的。
      下面我們對這兩種協議做簡單比較:
       使用 UDP 時,每個數據報中都給出了完整的地址信息,因此無需要建立發送方和接收方的連接。對于 TCP 協議,由于它是一個面向連接的協議,在 socket 之間進行數據傳輸之前必然要建立連接,所以在 TCP 中多了一個連接建立的時間。
    ?
      使用 UDP 傳輸數據時是有大小限制的,每個被傳輸的數據報必須限定在 64KB 之內。而 TCP 沒有這方面的限制,一旦連接建立起來,雙方的 socket 就可以按統一的格式傳輸大量的數據。 UDP 是一個不可靠的協議,發送方所發送的數據報并不一定以相同的次序到達接收方。而 TCP 是一個可靠的協議,它確保接收方完全正確地獲取發送方所發送的全部數據。
       總之, TCP 在網絡通信上有極強的生命力,例如遠程連接( Telnet )和文件傳輸( FTP )都需要不定長度的數據被可靠地傳輸。相比之下 UDP 操作簡單,而且僅需要較少的監護,因此通常用于局域網高可靠性的分散系統中 client/server 應用程序。
       讀者可能要問,既然有了保證可靠傳輸的 TCP 協議,為什么還要非可靠傳輸的 UDP 協議呢?主要的原因有兩個。一是可靠的傳輸是要付出代價的,對數據內容正確性的檢驗必然占用計算機的處理時間和網絡的帶寬,因此 TCP 傳輸的效率不如 UDP 高。二是在許多應用中并不需要保證嚴格的傳輸可靠性,比如視頻會議系統,并不要求音頻視頻數據絕對的正確,只要保證連貫性就可以了,這種情況下顯然使用 UDP 會更合理一些。

    8.2 基于URL的高層次Java網絡編程

    8.2.1一致資源定位器URL

    URL(Uniform Resource Locator) 是一致資源定位器的簡稱,它表示 Internet 上某一資源的地址。通過 URL 我們可以訪問 Internet 上的各種網絡資源,比如最常見的 WWW FTP 站點。瀏覽器通過解析給定的 URL 可以在網絡上查找相應的文件或其他資源。

    8.2.2 URL的組成

    protocol://resourceName
      協議名( protocol )指明獲取資源所使用的傳輸協議,如 http ftp gopher file 等,資源名( resourceName )則應該是資源的完整地址,包括主機名、端口號、文件名或文件內部的一個引用。 例如:
       http://www.sun.com/ 協議名 :// 主機名
       http://home.netscape.com/home/welcome.html 協議名 :// 機器名+文件名
       http://www.gamelan.com:80/Gamelan/network.html#BOTTOM 協議名 :// 機器名+端口號+文件名+內部引用 .

    8.2.3 創建一個URL

    為了表示 URL, java.net中實現了類URL。我們可以通過下面的構造方法來初始化一個URL對象:
      (1) public URL (String spec);
         通過一個表示URL地址的字符串可以構造一個URL對象。
         URL urlBase=new URL("http://www. 263.net/")
      (2) public URL(URL context, String spec);
         通過基URL和相對URL構造一個URL對象。
         URL net263=new URL ("http://www.263.net/");
         URL index263=new URL(net263, "index.html")
      (3) public URL(String protocol, String host, String file);
         new URL("http", "www.gamelan.com", "/pages/Gamelan.net. html");
      (4) public URL(String protocol, String host, int port, String file);
         URL gamelan=new URL("http", "www.gamelan.com", 80, "Pages/Gamelan.network.html");

      注意:URL的構造方法都聲明拋棄非運行時例外(MalformedURLException),因此生成URL對象時,我們必須要對這一例外進行處理,通常是用try-catch語句進行捕獲。格式如下:

    try{
          URL myURL= new URL(…)
       }catch (MalformedURLException e){
          }

    8.2.4 解析一個URL

    一個URL對象生成后,其屬性是不能被改變的,但是我們可以通過類URL所提供的方法來獲取這些屬性:
       public String getProtocol() 獲取該URL的協議名。
       public String getHost() 獲取該URL的主機名。
       public int getPort() 獲取該URL的端口號,如果沒有設置端口,返回-1。
       public String getFile() 獲取該URL的文件名。
       public String getRef() 獲取該URL在文件中的相對位置。
       public String getQuery() 獲取該URL的查詢信息。
       public String getPath() 獲取該URL的路徑
       public String getAuthority() 獲取該URL的權限信息
        public String getUserInfo() 獲得使用者的信息
         public String getRef() 獲得該 URL 的錨

    8.2.5 從URL讀取WWW網絡資源

    當我們得到一個 URL 對象后,就可以通過它讀取指定的 WWW 資源。這時我們將使用 URL 的方法 openStream() ,其定義為:
              InputStream openStream();
      
      方法 openSteam() 與指定的 URL 建立連接并返回 InputStream 類的對象以從這一連接中讀取數據。
       public class URLReader {
       public static void main(String[] args) throws Exception {
                           // 聲明拋出所有例外
         URL tirc = new URL("http://www.tirc1.cs.tsinghua.edu.cn/");
                           // 構建一 URL 對象
         BufferedReader in = new BufferedReader(new InputStreamReader(tirc.openStream()));
         // 使用 openStream 得到一輸入流并由此構造一個 BufferedReader 對象
         String inputLine;
         while ((inputLine = in.readLine()) != null)
                      // 從輸入流不斷的讀數據,直到讀完為止
            System.out.println(inputLine); // 把讀入的數據打印到屏幕上
         in.close(); // 關閉輸入流
       }
       }

    8.2.6 通過URLConnetction連接WWW

    通過 URL 的方法 openStream() ,我們只能從網絡上讀取數據,如果我們同時還想輸出數據,例如向服務器端的 CGI 程序發送一些數據,我們必須先與 URL 建立連接,然后才能對其進行讀寫,這時就要用到類 URLConnection 了。 CGI 是公共網關接口( Common Gateway Interface )的簡稱,它是用戶瀏覽器和服務器端的應用程序進行連接的接口,有關 CGI 程序設計,請讀者參考有關書籍。
       URLConnection 也在包 java.net 中定義,它表示 Java 程序和 URL 在網絡上的通信連接。當與一個 URL 建立連接時,首先要在一個 URL 對象上通過方法 openConnection() 生成對應的 URLConnection 對象。例如下面的程序段首先生成一個指向地址 http://edu.chinaren.com/index.shtml 的對象,然后用 openConnection ()打開該 URL 對象上的一個連接,返回一個 URLConnection 對象。如果連接過程失敗,將產生 IOException.
       Try{
         URL netchinaren = new URL ("http://edu.chinaren.com/index.shtml");
         URLConnectonn tc = netchinaren.openConnection();
       }catch(MalformedURLException e){ // 創建 URL() 對象失敗
      
       }catch (IOException e){ //openConnection() 失敗
      
       }
       類 URLConnection 提供了很多方法來設置或獲取連接參數,程序設計時最常使用的是 getInputStream() getOurputStream(), 其定義為:
          InputSteram getInputSteram();
          OutputSteram getOutputStream();
       通過返回的輸入 / 輸出流我們可以與遠程對象進行通信。看下面的例子:
       URL url =new URL ("http://www.javasoft.com/cgi-bin/backwards");
       // 創建一 URL 對象
       URLConnectin con=url.openConnection();
       // URL 對象獲取 URLConnection 對象
        DataInputStream dis=new DataInputStream (con.getInputSteam());
       // URLConnection 獲取輸入流,并構造 DataInputStream 對象
       PrintStream ps=new PrintSteam(con.getOutupSteam());
       // URLConnection 獲取輸出流,并構造 PrintStream 對象
       String line=dis.readLine(); // 從服務器讀入一行
       ps.println("client…"); // 向服務器寫出字符串 "client…"
        其中 backwards 為服務器端的 CGI 程序。實際上,類 URL 的方法 openSteam ()是通過 URLConnection 來實現的。它等價于
         openConnection().getInputStream();
       基于 URL 的網絡編程在底層其實還是基于下面要講的 Socket 接口的。 WWW FTP 等標準化的網絡服務都是基于 TCP 協議的,所以本質上講 URL 編程也是基于 TCP 的一種應用 .

    8.3 基于Socket的低層次Java網絡編程

    8.3.1 Socket通訊

    網絡上的兩個程序通過一個雙向的通訊連接實現數據的交換,這個雙向鏈路的一端稱為一個 Socket Socket 通常用來實現客戶方和服務方的連接。 Socket TCP/IP 協議的一個十分流行的編程界面,一個 Socket 由一個 IP 地址和一個端口號唯一確定。
      在傳統的 UNIX 環境下可以操作 TCP/IP 協議的接口不止 Socket 一個, Socket 所支持的協議種類也不光 TCP/IP 一種,因此兩者之間是沒有必然聯系的。在 Java 環境下, Socket 編程主要是指基于 TCP/IP 協議的網絡編程。

    8.3.2 Socket通訊的一般過程

    使用 Socket 進行 Client/Server 程序設計的一般連接過程是這樣的: Server Listen( 監聽 ) 某個端口是否有連接請求, Client 端向 Server 端發出 Connect( 連接 ) 請求, Server 端向 Client 端發回 Accept (接受)消息。一個連接就建立起來了。 Server 端和 Client 端都可以通過 Send Write 等方法與對方通信。

    對于一個功能齊全的 Socket ,都要包含以下基本結構,其工作過程包含以下四個基本的步驟:
      ( 1 創建 Socket
      ( 2 打開連接到 Socket 的輸入 / 出流;
      ( 3 按照一定的協議對 Socket 進行讀 / 寫操作;
      ( 4 關閉 Socket.

    8.3.3 創建Socket

    java 在包 java.net 中提供了兩個類 Socket ServerSocket ,分別用來表示雙向連接的客戶端和服務端 。這是兩個封裝得非常好的類,使用很方便。其構造方法如下:
       Socket(InetAddress address, int port);
       Socket(InetAddress address, int port, boolean stream);
       Socket(String host, int prot);
       Socket(String host, int prot, boolean stream);
       Socket(SocketImpl impl)
       Socket(String host, int port, InetAddress localAddr, int localPort)
       Socket(InetAddress address, int port, InetAddress localAddr, int localPort)
       ServerSocket(int port);
       ServerSocket(int port, int backlog);
       ServerSocket(int port, int backlog, InetAddress bindAddr)
       其中 address host port 分別是雙向連接中另一方的 IP 地址、主機名和端口號, stream 指明 socket 是流 socket 還是數據報 socket localPort 表示本地主機的端口號, localAddr bindAddr 是本地機器的地址( ServerSocket 的主機地址), impl socket 的父類,既可以用來創建 serverSocket 又可以用來創建 Socket count 則表示服務端所能支持的最大連接數。例如:
        Socket client = new Socket("127.0.01.", 80);
       ServerSocket server = new ServerSocket(80);
       注意,在選擇端口時,必須小心。每一個端口提供一種特定的服務,只有給出正確的端口,才能獲得相應的服務。 0~1023 的端口號為系統所保留,例如 http 服務的端口號為 80,telnet 服務的端口號為 21,ftp 服務的端口號為 23, 所以我們在選擇端口號時,最好選擇一個大于 1023 的數以防止發生沖突。
       在創建 socket 時如果發生錯誤,將產生 IOException ,在程序中必須對之作出處理。所以在創建 Socket ServerSocket 是必須捕獲或拋出例外。

    8.3.8 簡單的Client/Server程序設計

    下面我們給出一個用 Socket 實現的客戶和服務器交互的典型的 C/S 結構的演示程序,讀者通過仔細閱讀該程序,會對前面所討論的各個概念有更深刻的認識。程序的意義請參考注釋。

    1. 客戶端程序
      import java.io.*;
      import java.net.*;
      public class TalkClient {
        public static void main(String args[]) {
          try{
            Socket socket=new Socket("127.0.0.1",4700);
            
    //向本機的4700端口發出客戶請求
            BufferedReader sin=new BufferedReader(new InputStreamReader(System.in));
            
    //由系統標準輸入設備構造BufferedReader對象
            PrintWriter os=new PrintWriter(socket.getOutputStream());
            
    //由Socket對象得到輸出流,并構造PrintWriter對象
            BufferedReader is=new BufferedReader(new InputStreamReader(socket.getInputStream()));
            
    //由Socket對象得到輸入流,并構造相應的BufferedReader對象
            String readline;
            readline=sin.readLine();
    //從系統標準輸入讀入一字符串
            while(!readline.equals("bye")){
            
    //若從標準輸入讀入的字符串為 "bye"則停止循環
              os.println(readline);
              
    //將從系統標準輸入讀入的字符串輸出到Server
              os.flush();
              
    //刷新輸出流,使Server馬上收到該字符串
              System.out.println("Client:"+readline);

              //在系統標準輸出上打印讀入的字符串

              System.out.println("Server:"+is.readLine());
              
    //從Server讀入一字符串,并打印到標準輸出上
              readline=sin.readLine();
    //從系統標準輸入讀入一字符串
            }
    //繼續循環
            os.close();
    //關閉Socket輸出流
            is.close();
    //關閉Socket輸入流
            socket.close();
    //關閉Socket
          }catch(Exception e) {
            System.out.println("Error"+e);
    //出錯,則打印出錯信息
          }
      }
    }

     2. 服務器端程序
      import java.io.*;
      import java.net.*;
      import java.applet.Applet;
      public class TalkServer{
        public static void main(String args[]) {
          try{
            ServerSocket server=null;
            try{
              server=new ServerSocket(4700);
            
    //創建一個ServerSocket在端口4700監聽客戶請求
            }catch(Exception e) {
              System.out.println("can not listen to:"+e);
            
    //出錯,打印出錯信息
            }

             Socket socket=null;
            try{
              socket=server.accept();
              
    //使用accept()阻塞等待客戶請求,有客戶
              //請求到來則產生一個Socket對象,并繼續執行

            }catch(Exception e) {
              System.out.println("Error."+e);
              
    //出錯,打印出錯信息
            }
            String line;
            BufferedReader is=new BufferedReader(new InputStreamReader(socket.getInputStream()));
             
    //由Socket對象得到輸入流,并構造相應的BufferedReader對象
            PrintWriter os=newPrintWriter(socket.getOutputStream());
             
    //由Socket對象得到輸出流,并構造PrintWriter對象
            BufferedReader sin=new BufferedReader(new InputStreamReader(System.in));
             
    //由系統標準輸入設備構造BufferedReader對象

            System.out.println("Client:"+is.readLine());
            
    //在標準輸出上打印從客戶端讀入的字符串
            line=sin.readLine();
            
    //從標準輸入讀入一字符串
            while(!line.equals("bye")){
            
    //如果該字符串為 "bye",則停止循環
              os.println(line);
              
    //向客戶端輸出該字符串
              os.flush();
              
    //刷新輸出流,使Client馬上收到該字符串
              System.out.println("Server:"+line);
              
    //在系統標準輸出上打印讀入的字符串
              System.out.println("Client:"+is.readLine());
              
    //從Client讀入一字符串,并打印到標準輸出上
              line=sin.readLine();
              
    //從系統標準輸入讀入一字符串
            }  
    //繼續循環
            os.close();
    //關閉Socket輸出流
            is.close();
    //關閉Socket輸入流
            socket.close();
    //關閉Socket
            server.close();
    //關閉ServerSocket
          }catch(Exception e){
            System.out.println("Error:"+e);
            
    //出錯,打印出錯信息
          }
        }
      }

    8.3.9 支持多客戶的 client/server 程序設計

    前面提供的 Client/Server 程序只能實現 Server 和一個客戶的對話。在實際應用中,往往是在服務器上運行一個永久的程序,它可以接收來自其他多個客戶端的請求,提供相應的服務。為了實現在服務器方給多個客戶提供服務的功能,需要對上面的程序進行改造,利用多線程實現多客戶機制。服務器總是在指定的端口上監聽是否有客戶請求,一旦監聽到客戶請求,服務器就會啟動一個專門的服務線程來響應該客戶的請求,而服務器本身在啟動完線程之后馬上又進入監聽狀態,等待下一個客戶的到來。

    ServerSocket serverSocket=null;
         boolean listening=true;
         try{
           serverSocket=new ServerSocket(4700);
           // 創建一個 ServerSocket 在端口 4700 監聽客戶請求
         }catch(IOException e) {    }
         while(listening){ // 永遠循環監聽
            new ServerThread(serverSocket.accept(),clientnum).start();
           // 監聽到客戶請求,根據得到的 Socket 對象和
           客戶計數創建服務線程,并啟動之
           clientnum++; // 增加客戶計數
         }
         serverSocket.close(); // 關閉 ServerSocket

    設計 ServerThread

      public class ServerThread extends Thread{
        Socket socket=null; // 保存與本線程相關的 Socket 對象
        int clientnum; // 保存本進程的客戶計數
        public ServerThread(Socket socket,int num) { // 構造函數
          this.socket=socket; // 初始化 socket 變量
         clientnum=num+1; // 初始化 clientnum 變量
        }
        public void run() { // 線程主體
         try{// 在這里實現數據的接受和發送 }

    8.3.10 據報 Datagram 通訊

    前面在介紹 TCP/IP 協議的時候,我們已經提到,在 TCP/IP 協議的傳輸層除了 TCP 協議之外還有一個 UDP 協議,相比而言 UDP 的應用不如 TCP 廣泛,幾個標準的應用層協議 HTTP FTP SMTP… 使用的都是 TCP 協議。但是,隨著計算機網絡的發展, UDP 協議正越來越來顯示出其威力,尤其是在需要很強的實時交互性的場合,如網絡游戲,視頻會議等, UDP 更是顯示出極強的威力,下面我們就介紹一下 Java 環境下如何實現 UDP 網絡傳輸。

    8.3.11 什么是 Datagram

    所謂數據報( Datagram )就跟日常生活中的郵件系統一樣,是不能保證可靠的寄到的,而面向鏈接的 TCP 就好比電話,雙方能肯定對方接受到了信息。在本章前面,我們已經對 UDP TCP 進行了比較,在這里再稍作小節:
       TCP ,可靠,傳輸大小無限制,但是需要連接建立時間,差錯控制開銷大。
       UDP ,不可靠,差錯控制開銷較小,傳輸大小限制在 64K 以下,不需要建立連接。

    8.3.12 Datagram 通訊的表示方法: DatagramSocket DatagramPacket

    java.net 中提供了兩個類 DatagramSocket DatagramPacket 用來支持數據報通信, DatagramSocket 用于在程序之間建立傳送數據報的通信連接, DatagramPacket 則用來表示一個數據報。 先來看一下 DatagramSocket 的構造方法:
        DatagramSocket ();
        DatagramSocket int prot ;
        DatagramSocket(int port, InetAddress laddr)
          其中, port 指明 socket 所使用的端口號,如果未指明端口號,則把 socket 連接到本地主機上一個可用的端口。 laddr 指明一個可用的本地地址。給出端口號時要保證不發生端口沖突,否則會生成 SocketException 類例外。注意:上述的兩個構造方法都聲明拋棄非運行時例外 SocketException ,程序中必須進行處理,或者捕獲、或者聲明拋棄。
    ??
    用數據報方式編寫 client/server 程序時,無論在客戶方還是服務方,首先都要建立一個 DatagramSocket 對象,用來接收或發送數據報,然后使用 DatagramPacket 類對象作為傳輸數據的載體。 下面看一下 DatagramPacket 的構造方法
        DatagramPacket byte buf[],int length );
        DatagramPacket(byte buf[], int length, InetAddress addr, int port);
        DatagramPacket(byte[] buf, int offset, int length)
        DatagramPacket(byte[] buf, int offset, int length, InetAddress address, int port)

      其中, buf 中存放數據報數據, length 為數據報中數據的長度, addr port 旨明目的地址, offset 指明了數據報的位移量。
       在接收數據前,應該采用上面的第一種方法生成一個 DatagramPacket 對象,給出接收數據的緩沖區及其長度。然后調用 DatagramSocket 的方法 receive() 等待數據報的到來, receive() 將一直等待,直到收到一個數據報為止。
       DatagramPacket packet=new DatagramPacket(buf, 256);
       Socket.receive (packet);
       發送數據前,也要先生成一個新的 DatagramPacket 對象,這時要使用上面的第二種構造方法,在給出存放發送數據的緩沖區的同時,還要給出完整的目的地址,包括 IP 地址和端口號。發送數據是通過 DatagramSocket 的方法 send() 實現的, send() 根據數據報的目的地址來尋徑,以傳遞數據報。
       DatagramPacket packet=new DatagramPacket(buf, length, address, port);
       Socket.send(packet)
    ???
    在構造數據報時,要給出 InetAddress 類參數。類 InetAddress 在包 java.net 中定義,用來表示一個 Internet 地址,我們可以通過它提供的類方法 getByName ()從一個表示主機名的字符串獲取該主機的 IP 地址,然后再獲取相應的地址信息。

    8.3.14 用數據報進行廣播通訊

    DatagramSocket 只允許數據報發送一個目的地址, java.net 包中提供了一個類 MulticastSocket ,允許數據報以廣播方式發送到該端口的所有客戶。 MulticastSocket 用在客戶端,監聽服務器廣播來的數據。

    1. 客戶方程序 :MulticastClient.java
      import java.io.*;
      import java.net.*;
      import java.util.*;
      public class MulticastClient {
        public static void main(String args[]) throws IOException
        {
         MulticastSocket socket=new MulticastSocket(4446);
         
    //創建4446端口的廣播套接字
         InetAddress address=InetAddress.getByName("230.0.0.1");
         
    //得到230.0.0.1的地址信息
         socket.joinGroup(address);
         
    //使用joinGroup()將廣播套接字綁定到地址上
         DatagramPacket packet;

          for(int i=0;i<5;i++) {
           byte[] buf=new byte[256];
           
    //創建緩沖區

           packet=new DatagramPacket(buf,buf.length);
           
    //創建接收數據報
           socket.receive(packet);
    //接收
           String received=new String(packet.getData());
           
    //由接收到的數據報得到字節數組,
           
    //并由此構造一個String對象
           System.out.println("Quote of theMoment:"+received);
           
    //打印得到的字符串
         }
    //循環5次
         socket.leaveGroup(address);
         
    //把廣播套接字從地址上解除綁定
         socket.close();
    //關閉廣播套接字
       }
     }

     2. 服務器方程序:MulticastServer.java
      public class MulticastServer{
        public static void main(String args[]) throws java.io.IOException
        {
          new MulticastServerThread().start();
          
    //啟動一個服務器線程
        }
      }

     3. 程序MulticastServerThread.java
      import java.io.*;
      import java.net.*;
      import java.util.*;
      public class MulticastServerThread extends QuoteServerThread
      
    //從QuoteServerThread繼承得到新的服務器線程類MulticastServerThread
      {
        Private long FIVE_SECOND=5000;
    //定義常量,5秒鐘
        public MulticastServerThread(String name) throws IOException
        {
          super("MulticastServerThread");
          
    //調用父類,也就是QuoteServerThread的構造函數
        }

        public void run() //重寫父類的線程主體
        {
         while(moreQuotes) {
         
    //根據標志變量判斷是否繼續循環
          try{
            byte[] buf=new byte[256];
            
    //創建緩沖區
            String dString=null;
            if(in==null) dString=new Date().toString();
            
    //如果初始化的時候打開文件失敗了,
            //則使用日期作為要傳送的字符串

            else dString=getNextQuote();
            
    //否則調用成員函數從文件中讀出字符串
            buf=dString.getByte();
            
    //把String轉換成字節數組,以便傳送send it
            InetAddress group=InetAddress.getByName("230.0.0.1");
            
    //得到230.0.0.1的地址信息
            DatagramPacket packet=new DatagramPacket(buf,buf.length,group,4446);
            
    //根據緩沖區,廣播地址,和端口號創建DatagramPacket對象
            socket.send(packet);
    //發送該Packet
            try{
              sleep((long)(Math.random()*FIVE_SECONDS));
              
    //隨機等待一段時間,0~5秒之間
            }catch(InterruptedException e) { }
    //異常處理
          }catch(IOException e){
    //異常處理
            e.printStackTrace( );
    //打印錯誤棧

            moreQuotes=false; //置結束循環標志
          }
        }
        socket.close( );
    //關閉廣播套接口
       }
     }

    【本講小結】

    本講主要講解了 Java 環境下的網絡編程。因為 TCP/IP 協議是 Java 網絡編程的基礎知識,本講開篇重點介紹了 TCP/IP 協議中的一些概念, TCP/IP 協議本身是一個十分龐大的系統,用幾個小節是不可能講清楚的。所以我們只是聯系實際,講解了一些最基本的概念,幫助學生理解后面的相關內容。重點有一下幾個概念:主機名, IP ,端口,服務類型, TCP UDP
       后續的內容分為兩大塊,一塊是以 URL 為主線,講解如何通過 URL 類和 URLConnection 類訪問 WWW 網絡資源,由于使用 URL 十分方便直觀,盡管功能不是很強,還是值得推薦的一種網絡編程方法,尤其是對于初學者特別容易接受。本質上講, URL 網絡編程在傳輸層使用的還是 TCP 協議。
       另一塊是以 Socket 接口和 C/S 網絡編程模型為主線,依次講解了如何用 Java 實現基于 TCP C/S 結構,主要用到的類有 Socket ServerSocket 。以及如何用 Java 實現基于 UDP C/S 結構,還討論了一種特殊的傳輸方式,廣播方式,這種方式是 UDP 所特有的,主要用到的類有 DatagramSocket , DatagramPacket, MulticastSocket 。這一塊在 Java 網絡編程中相對而言是最難的(盡管 Java 在網絡編程這方面已經做的夠 " 傻瓜 " 了,但是網絡編程在其他環境下的卻是一件極為頭痛的事情,再 " 傻瓜 " 還是有一定的難度),也是功能最為強大的一部分 , 讀者應該好好研究,領悟其中的思想。
       最后要強調的是要學好 Java 網絡編程, Java 語言,最重要的還是在于多多練習!

    Trackback: http://tb.blog.csdn.net/TrackBack.aspx?PostId=102420

    posted on 2006-07-15 13:39 謝瑋 閱讀(209) 評論(0)  編輯  收藏 所屬分類: java應用程序

    導航

    統計

    常用鏈接

    留言簿(1)

    隨筆檔案

    文章分類

    文章檔案

    搜索

    最新評論

    主站蜘蛛池模板: 久久av无码专区亚洲av桃花岛| 无人在线观看完整免费版视频| 国产精品免费大片一区二区| 日韩毛片在线免费观看| 美女视频黄频a免费大全视频 | 国内精品免费视频自在线| 无码国产精品一区二区免费 | 三年片在线观看免费西瓜视频| 一级成人毛片免费观看| 日韩毛片一区视频免费| 一级毛片视频免费| 三年在线观看免费观看完整版中文| 国产精品九九久久免费视频| aa级女人大片喷水视频免费| 国产综合免费精品久久久| 中国一级全黄的免费观看| 免费观看成人久久网免费观看| 日本免费污片中国特一级| 日韩精品无码免费一区二区三区| 日韩免费无码一区二区三区 | 手机看片国产免费永久| 久久国产精品国产自线拍免费| 日本一道本不卡免费| 最近免费中文字幕mv电影| 黄瓜视频影院在线观看免费| 久久久久国产精品免费免费搜索 | av大片在线无码免费| 扒开双腿猛进入爽爽免费视频 | 久久国产免费一区二区三区| 最近免费中文字幕高清大全| 免费看黄视频网站| 四虎永久在线精品视频免费观看| 国产成人精品曰本亚洲79ren| 久久亚洲精品中文字幕无码| 亚洲制服丝袜在线播放| 亚洲狠狠婷婷综合久久| 国产美女视频免费观看的网站 | eeuss影院ss奇兵免费com| 男人的天堂网免费网站| 国产免费久久精品99re丫y| 国产婷婷高清在线观看免费|