1. 程式人生 > >第十三章學習筆記

第十三章學習筆記

一,教材學習內容(13.Java網路程式設計)

1、URL類

使用URL建立物件的應用程式稱為客戶端程式。

URL的組成:

協議名:指明獲取資源所使用的傳輸協議,如HTTP,FTP,Gopher,File等

埠號:可選,表示連線的埠號,如預設將連線到協議預設的埠

資源名:是資源的完整地址,包括主機名,埠號,檔名或檔案內部的一個引用。

標記:可選,指檔案內的有特定標記的位置

1.1 URL類的構造方法

為表示URL,Java.net中實現了URL類,可通過下面的構造方法來初始化一個URL物件。

1)public URL(String spec);//通過一個表示URL地址的字串可以構造一個URL物件,如:URL urlbase=new URL(“http://www.163.com/”)

2)public URL(URL context,String spec);//通過基URL構造一個URL物件,如: URL com163=new URL(“http://www.163.com/”)

 URL index163=new URL(com163,”index.html”)

3)public URL(String protocol,String host,String file);//通過協議,域名及檔名構造一個url物件,如:URL gamelan=new URL(“http”,”www.gamelan.com”,”/pages/Gamelan.net.html”);

4)public URL(String protocol,String host,int port,String file);//通過協議,域名,埠號及檔名構造一個url物件,如:URL gamelan=new URL(“http”,”www.gamelan.com”,80,”/pages/Gamelan.net.html”);

注意:類URL的構造方法都可能會丟擲異常,因此生成URL物件時,必須要對這個Exception進行處理,通常使用try catch語句進行捕獲。

1.2 URL部分方法

String getPotocol() 獲取該URL的協議名

String getHost() 獲取該URL的主機名

Int getPort() 獲取該URL的埠號,如果沒有設定埠,返回-1

String getFile() 獲取該URL的檔名,如果沒有返回空串

String getRef() 獲取該URL中記錄的引用,如果URL不含引用,返回null

String getQuery() 獲取該URL的查詢資訊

String getPath() 獲取該URL的路徑

String getAuthority() 獲取該URL的許可權資訊

String getUserInfo() 獲得使用者的資訊
 

1.3 InetAddress類(主要用於其他類的方法引數)

具體使用:

import java.net.*; 
public class Example13_2 {
   public static void main(String args[]) {
      try{  InetAddress address_1=InetAddress.getByName("www.sina.com.cn");
           System.out.println(address_1.toString()); 
           InetAddress address_2=InetAddress.getByName("166.111.222.3");
           System.out.println(address_2.toString());
      }
      catch(UnknownHostException e) {
           System.out.println("無法找到 www.sina.com.cn");
      } 
   }
}


1.3 套接字(IP+Port)

其中埠號(Port)規定為一個十六位的0~65535之間的整數,其中0~1023被預先定義的服務通訊佔用。

當兩個程式需要通訊時,它們可以通過Socket類建立套接字物件並連線在一起。

1.3.1 客戶端套接字(Socket類)

try{Socket clientSocket=new Socket("http://192.168.0.78",2010);
}
catch(IOExeception){}

當客戶端套接字物件建好後,可以使用getInputStream()和getOutputStream()方法向客戶端輸入輸出資料。

1.3.2 伺服器端套接字與ServerSocket物件

為了能使客戶成功連線到伺服器,伺服器必須建立一個ServerSocket物件,該物件的作用在於將客戶端和伺服器端的套接字連線在一起。

使用try-catch語句塊建立ServerSocket物件。

try{ServerSocket Serverforclient=new ServerSocket(2010);
}
catch(IOExeception){}

建立完畢後,就可以使用accept()方法連線兩邊的套接字。

需要注意的是,accept()也會造成程式阻塞。

import java.io.*;
import java.net.*;
public class Client {
   public static void main(String args[]) {
      String [] mess ={"2010世界盃在哪舉行?","巴西進入世界盃了碼?","中國進入世界盃了碼?"};
      Socket mysocket;
      DataInputStream in=null;
      DataOutputStream out=null;
      try{  mysocket=new Socket("127.0.0.1",2010);
            in=new DataInputStream(mysocket.getInputStream());
            out=new DataOutputStream(mysocket.getOutputStream()); 
            for(int i=0;i<mess.length;i++) {
              out.writeUTF(mess[i]);
              String  s=in.readUTF();   //in讀取資訊,堵塞狀態
              System.out.println("客戶收到伺服器的回答:"+s);
              Thread.sleep(500);
            } 
       }
       catch(Exception e) {
            System.out.println("伺服器已斷開"+e);
       }
   } 
}
import java.io.*;
import java.net.*;
public class Server {
   public static void main(String args[]) {
      String [] answer ={"南非","進入世界盃了","哈哈...問題真逗!"};
      ServerSocket serverForClient=null;
      Socket socketOnServer=null;
      DataOutputStream out=null;
      DataInputStream  in=null;
      try { serverForClient = new ServerSocket(2010);
      }
      catch(IOException e1) {
            System.out.println(e1);
      } 
      try{ System.out.println("等待客戶呼叫");
           socketOnServer = serverForClient.accept(); //堵塞狀態,除非有客戶呼叫
           out=new DataOutputStream(socketOnServer.getOutputStream());
           in=new DataInputStream(socketOnServer.getInputStream());
           for(int i=0;i<answer.length;i++) {
              String s=in.readUTF(); // in讀取資訊,堵塞狀態
              System.out.println("伺服器收到客戶的提問:"+s);
              out.writeUTF(answer[i]);
              Thread.sleep(500);
           }
      }
      catch(Exception e) {
          System.out.println("客戶已斷開"+e);
      }
   }
}

 

1.4 使用多執行緒技術

目的:為每個客戶端啟動一個執行緒,以滿足每個客戶的需要。

import java.io.*;
import java.net.*;
import java.util.*;
public class Client  {
   public static void main(String args[]) {
      Scanner scanner = new Scanner(System.in);
      Socket mysocket=null;
      DataInputStream in=null;
      DataOutputStream out=null;
      Thread readData ; 
      Read read=null;
      try{  mysocket=new Socket();
            read = new Read();
            readData = new Thread(read);
            System.out.print("輸入伺服器的IP:");
            String IP = scanner.nextLine();
            System.out.print("輸入埠號:");
            int port = scanner.nextInt();
            if(mysocket.isConnected()){}
            else{
              InetAddress  address=InetAddress.getByName(IP);
              InetSocketAddress socketAddress=new InetSocketAddress(address,port);
              mysocket.connect(socketAddress); 
              in =new DataInputStream(mysocket.getInputStream());
              out = new DataOutputStream(mysocket.getOutputStream());
              read.setDataInputStream(in);
              readData.start();
            }
       }
       catch(Exception e) {
            System.out.println("伺服器已斷開"+e);
       }
       System.out.print("輸入園的半徑(放棄請輸入N):");
       while(scanner.hasNext()) {
           double radius=0; 
           try {
               radius = scanner.nextDouble();
           }
           catch(InputMismatchException exp){
              System.exit(0);
           }   
           try { 
               out.writeDouble(radius);
           }
           catch(Exception e) {}
       } 
   }
}
import java.io.*;
public class Read implements Runnable {
   DataInputStream in;
   public void setDataInputStream(DataInputStream in) {
      this.in = in;
   }
   public void run() {
      double result=0;
      while(true) {
        try{ result=in.readDouble();
             System.out.println("圓的面積:"+result);
             System.out.print("輸入園的半徑(放棄請輸入N):");
        }
        catch(IOException e) { 
             System.out.println("與伺服器已斷開"+e);
             break;
        }   
      }
   }
}
import java.io.*;
import java.net.*;
import java.util.*;
public class Server {
   public static void main(String args[]) {
      ServerSocket server=null;
      ServerThread thread;
      Socket you=null;
      while(true) {
        try{  server=new ServerSocket(2010);
        }
        catch(IOException e1) { 
              System.out.println("正在監聽"); //ServerSocket物件不能重複建立
        } 
        try{  System.out.println(" 等待客戶呼叫");
              you=server.accept();
              System.out.println("客戶的地址:"+you.getInetAddress());
        } 
        catch (IOException e) {
              System.out.println("正在等待客戶");
        }
        if(you!=null) { 
              new ServerThread(you).start(); //為每個客戶啟動一個專門的執行緒  
        }
      }
   }
}
class ServerThread extends Thread {
   Socket socket;
   DataOutputStream out=null;
   DataInputStream  in=null;
   String s=null;
   ServerThread(Socket t) {
      socket=t;
      try {  out=new DataOutputStream(socket.getOutputStream());
             in=new DataInputStream(socket.getInputStream());
      }
      catch (IOException e){}
   }  
   public void run() {        
      while(true) {
         try{  double r=in.readDouble();//堵塞狀態,除非讀取到資訊
               double area=Math.PI*r*r;
               out.writeDouble(area);
         }
         catch (IOException e) {
               System.out.println("客戶離開");
                return;
         }
      }
   } 
}

2、UDP資料包

套接字是基於TCP協議的網路通訊,而基於UDP的網路通訊方式的資訊傳遞更快,但不提供可靠性的保證。

import java.net.*;
import java.util.*;
public class LiSi  {
   public static void main(String args[]) {
      Scanner scanner = new Scanner(System.in);
      Thread readData ; 
      ReceiveLetterForLi receiver = new ReceiveLetterForLi();
      try{  readData = new Thread(receiver);
            readData.start();           //負責接收資訊的執行緒 
            byte [] buffer=new byte[1];
            InetAddress address=InetAddress.getByName("127.0.0.1");
            DatagramPacket dataPack=
            new DatagramPacket(buffer,buffer.length, address,888);
            DatagramSocket postman=new DatagramSocket();
            System.out.print("輸入傳送給張三的資訊:");
            while(scanner.hasNext()) {
                String mess = scanner.nextLine();
                buffer=mess.getBytes();
                if(mess.length()==0) 
                    System.exit(0);
                buffer=mess.getBytes();
                dataPack.setData(buffer);
                postman.send(dataPack);  
                System.out.print("繼續輸入傳送給張三的資訊:");
            }
       }
       catch(Exception e) {
            System.out.println(e);
       }
   }
}
import java.net.*;
public class ReceiveLetterForLi implements Runnable {
   public void run() {
      DatagramPacket pack=null;
      DatagramSocket postman=null;
      byte data[]=new byte[8192];
      try{  pack=new DatagramPacket(data,data.length);
            postman = new DatagramSocket(666);
      }
      catch(Exception e){} 
      while(true) {  
        if(postman==null) break;
        else
          try{ postman.receive(pack); 
               String message=new String(pack.getData(),0,pack.getLength());
               System.out.printf("%25s\n","收到:"+message);
          }
          catch(Exception e){}
      } 
   }
}
import java.net.*;
public class ReceiveLetterForZhang implements Runnable {
   public void run() {
      DatagramPacket pack=null;
      DatagramSocket postman=null;
      byte data[]=new byte[8192];
      try{  pack=new DatagramPacket(data,data.length);
            postman = new DatagramSocket(888);
      }
      catch(Exception e){} 
      while(true) {  
        if(postman==null) break;
        else
          try{ postman.receive(pack); 
               String message=new String(pack.getData(),0,pack.getLength());
               System.out.printf("%25s\n","收到:"+message);
          }
          catch(Exception e){}
      } 
   }
}
import java.net.*;
import java.util.*;
public class ZhangSan  {
   public static void main(String args[]) {
      Scanner scanner = new Scanner(System.in);
      Thread readData ; 
      ReceiveLetterForZhang receiver = new ReceiveLetterForZhang();
      try{ readData = new Thread(receiver);
            readData.start();           //負責接收資訊的執行緒 
            byte [] buffer=new byte[1];
            InetAddress address=InetAddress.getByName("127.0.0.1");
            DatagramPacket dataPack=
            new DatagramPacket(buffer,buffer.length, address,666);
            DatagramSocket postman=new DatagramSocket();
            System.out.print("輸入傳送給李四的資訊:");
            while(scanner.hasNext()) {
                String mess = scanner.nextLine();
                buffer=mess.getBytes();
                if(mess.length()==0) 
                    System.exit(0);
                buffer=mess.getBytes();
                dataPack.setData(buffer);
                postman.send(dataPack);  
                System.out.print("繼續輸入傳送給李四的資訊:");
            }
       }
       catch(Exception e) {
            System.out.println(e);
       }
   }
}