Java網絡編程

8.1 網絡編程基本概念,TCP/IP協議簡介<o:p></o:p>

8.1.1 網絡基礎知識<o:p></o:p>

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

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

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

8.2 基於URL的高層次Java網絡編程<o:p></o:p>

8.2.1一致資源定位器URL<o:p></o:p>

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

8.2.2 URL的組成

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

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){
    }<o:p></o:p>

8.2.4 解析一個URL<o:p></o:p>

一個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的錨<o:p></o:p>

8.2.5 從URL讀取WWW網絡資源<o:p></o:p>

當我們得到一個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(); //關閉輸入流
  }
  }<o:p></o:p>

8.2.6 通過URLConnetction連接WWW<o:p></o:p>

通過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接口的。WWWFTP等標準化的網絡服務都是基於TCP協議的,所以本質上講URL編程也是基於TCP的一種應用.<o:p></o:p>

8.3 基於Socket的低層次Java網絡編程<o:p></o:p>

8.3.1 Socket通訊<o:p></o:p>

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

8.3.2 Socket通訊的一般過程<o:p></o:p>

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

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

8.3.3 創建Socket<o:p></o:p>

java在包java.net中提供了兩個類SocketServerSocket,分別用來表示雙向連接的客戶端和服務端。這是兩個封裝得非常好的類,使用很方便。其構造方法如下:
  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)
  其中addresshostport分別是雙向連接中另一方的IP地址、主機名和端口號,stream指明socket是流socket還是數據報socketlocalPort表示本地主機的端口號,localAddrbindAddr是本地機器的地址(ServerSocket的主機地址),implsocket的父類,既可以用來創建serverSocket又可以用來創建Socketcount則表示服務端所能支持的最大連接數。例如:
  Socket client = new Socket("127.0.01.", 80);
  ServerSocket server = new ServerSocket(80);
  注意,在選擇端口時,必須小心。每一個端口提供一種特定的服務,只有給出正確的端口,才能獲得相應的服務。0~1023的端口號爲系統所保留,例如http服務的端口號爲80,telnet服務的端口號爲21,ftp服務的端口號爲23,

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