1. 程式人生 > >基於Socket的低層次Java網絡編程

基於Socket的低層次Java網絡編程

大連 設備 pri 過程 input 127.0.0.1 sta list lose

  • Socket通訊

網絡上的兩個程序通過一個雙向的通訊連接實現數據的交換,這個雙向鏈路的一端稱為一個Socket。Socket通常用來實現客戶方和服務方的連接。Socket是TCP/IP協議的一個十分流行的編程界面,一個Socket由一個IP地址和一個端口號唯一確定。

在傳統的UNIX環境下可以操作TCP/IP協議的接口不止Socket一個,Socket所支持的協議種類也不光TCP/IP一種,因此兩者之間是沒有必然聯系的。在Java環境下,Socket編程主要是指基於TCP/IP協議的網絡編程。

  • 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。

  • 創建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是必須捕獲或拋出例外。

  • 簡單的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); //出錯,則打印出錯信息

      }

  }

}
  1. 服務器端程序

  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); 

        //出錯,打印出錯信息

      }

    }

  }

基於Socket的低層次Java網絡編程