網路應用模式主要有:
www(萬維網)就是建立在客戶機/伺服器模式上,以HTML語言和HTTP協定為基礎,能夠提供各種Internet服務的資訊瀏覽系統。網路資訊放在主機的不同位置,www伺服器利用超文本連結連結各項資訊。 www客戶機(瀏覽器Brower)負責與伺服器建立聯繫,向伺服器發送請求,處理HTML超媒體,提供圖形使用者介面(GUI),顯示資訊等。
在客戶機/伺服器工作模式中,在Server端,要準備接受多個Client端電腦的通訊。為此,除用IP位址標識Internet上的電腦之外,另還引入連接埠號,並以連接埠號標識正在Server端後台服務的執行緒。連接埠號碼與IP位址的組合稱為網路套接字(socket)。
Java語言在實作C/S模式中,套接字分為兩類:
Server機透過連接埠(匯流排I/O位址)提供面向Client機的服務;Server機在它的幾個不同連接埠分別同時提供幾種不同的服務。 Client接入Server的某一端口,透過這個端口提請Server機為其服務。規定:連接埠號碼0~1023供系統專用。例如,HTTP協定在連接埠80,telnet協定在連接埠23。埠1024~65535供應用程式使用。
當Client程式和Server程式需要通訊時,可以用Socket類別建立套接字連線。套接字連線可想像為一個電話呼叫:最初是Client程式建立呼叫,Server程式監聽;呼叫完成後,任何一方都可以隨時講話。
雙方實現通訊有流式socket和資料報式socket兩種可選方式:
串流socket在Client程式和Server程式間建立通訊的通道。每個socket可以進行讀取和寫入兩種操作。對於任一端,與對方的通訊會話過程是:
建立socket連接,獲得輸入/輸出流,讀取數據/寫數據,通信完成後關閉socket(拆除連接)。
利用socket的建構方法,可以在客戶端建立到伺服器的套接字物件:
Socket(String host,int port):host是伺服器的IP位址,port是連接埠號,這些是預先約定的。
例如,代碼:
try{ Socket mySocket = new Socket(“http://www.weixueyuan.net” ,1860); }catch(IOException e){}
然後,用getInputStream()方法取得輸入流,用這個輸入流讀取伺服器放入「線路」的資訊;用getOutputStream()方法取得輸出流,用這個輸出流將資訊寫入「線路」。
利用ServerSocket的建構方法可以在伺服器建立接受客戶套接字的伺服器套接字物件:
ServerSocket(int port):指定連接埠號,建立一個ServerSocket物件。連接埠號port要與客戶呼叫的連接埠號碼相同。為此,用以下形式代碼:
try{ ServerSocket serverSocket = new ServerSocket(1860); }catch(IOException e){}
伺服器端程式在指定的連接埠監聽,當收到Client程式發出的服務請求時,建立一個套接字物件與該連接埠對應的Client程式通訊。例如,執行上述建立伺服器套接字物件的程式碼,確立了物件serverSocket後,就可能它使用accept()方法,得到Socket對象,接收Client程式來自套接字mySocket的資訊。如以下程式碼所示:
try{ Socket sc = serverSocket.accept();//ac是Socket物件}catch(IOException e){}
若要撤銷服務,可以關閉Socket物件sc:
sc.close();
【例】C/S模式中的Client端應用程式。這是一個Client端的流式Socket通訊的簡單實例,程式碼說明Client端程式的編寫方法。例中,Client程式向伺服器主機的連接埠4441提出請求,連線建立後完成伺服器的讀寫。
import java.io.*;import java.net.*;public class Client{ public static void main(String args[]){ String s = null;Socket mySocket; DataInputStream in = null;DataOutputStream out = null; try{ mySocket = new Socket(“localhost”,4441); in = new DataInputStream(mySocket.getInputStream()); out = new DataOutputStream(mySocket.getOutputStream()); out.writeUTF(“good server!”); while(true){ s = in.readUTF(); if(s== null) break; else System.out.println(s); } mySocket.close(); }catch(IOException e){ System.out.println(“can't connect”); } }}
【例】與Client端應用程式對應的Server端應用程式。程式在4441埠監聽,當偵測到有客戶機請求時,產生一個內為「客戶,你好,我是伺服器」的字串輸出到客戶端。
import java.io.*;import java.net.*;public class Server{ public static void main(String args[]){ ServerSocket server = null; Socket you = null;String s = null; DataOutputStream out = null; DataInputStreamStream in = null; try{ server = new ServerSocket(4441); }catch(IOException e1){ system.out.println(“ERROR:” +e1); } try{ you = server.accept(); in = new DataInputStream(you.getInputStream()); out = new DataOutputStream(you. getOutputStream() ); while(true){ s = in.readUTF(); if(s!=null) break; } out.writeUTF(“客戶,你好,我是伺服器”); out.close(); } catch(IOException e){System.out.println(“ERROR:”+e);} }}
為了充分發揮電腦的平行工作能力,可以把套接字連接工作讓一個執行緒完成。當客戶端要請求伺服器給予服務,或當伺服器端接收到一個客戶的服務請求,就啟動一個專門完成資訊通訊的線程,在該線程中建立輸入輸出流,並完成客戶端與伺服器端的資訊交流。
【例】 將套接字連接工作置於執行緒的客戶端小應用程式。介面在有一個發送訊息按紐、一個文字方塊和一個文字區。客戶端應用程式首先與伺服器建立套接字連線。使用資料輸入流in重複讀取伺服器放入線路裡的信息,將收到的資訊顯示在文字區中。志取的訊息是“結束”,則關閉套接字連接,並結束程式。使用者也可在文字方塊輸入訊息,並按下傳送訊息按鈕,則用戶端程式利用資料輸出流out,將文字方塊中的內容傳送給伺服器。
import java.net.*;import java.io.*;import java.awt.*;import javax.swing.*;import java.awt.event.*;import java.applet.*;public class Aclient extends Applet implements Runnable,ActionListener{ JButton button; JTextField textF; JTextArea textA; Socket socket; Thread thread; DataInputStream in; DataOutputStream out; public void init(){ setBackground(new Color(120,153,137)); setLayout(new BorderLayout()); Button = new JButton(“傳送訊息”); textF = new JTextFiel ; textA = new JTextArea(20,30); setSize(450,350); JPanel p = new JPanel(); p.add(textF); p.add(button); add(textA,”Center”); add(p,”South”); button.addActionListener(this ); } public void start(){ try{ socket = new Socket(this.getCodeBase().getHost(),4441); in = new DataInputStream(socket.getInputStream()); out = new DataOutputStream(socket.getOutputStream()); }catch(IOException e){} if(socket.getOutputStream()); }catch(IOException e){} if(ththread ==null){ thread = new Thread(this); thread.setPriority(Thread.MIN_PRIORITY); thread.start(); } } public void run(){ String s = null; while(true){ try{ s = in.readUTF(); }catch(IOException e){ } if(s.equals(“結束”)){ try{ socket.close();break; }catch(IOException e){} }else texA.append(s + “/n”); } } public void actionPerformed(ActionEvent e){ if(e.getSource()==button){ String s = textF.getText(); if (s! = null){ try{ out.writeUTF(s); }catch(IOException e1){} } else{ try{ out.writeUTF(“請說”); } catch(IOException e1){} } } }}
【例】程式以端4441建立與客戶端的套接字連接,伺服器端收到客戶端的申請後,以客戶的套接字建立一個線程,並啟動。如果沒有客戶申請,則繼續監聽客戶的申請。執行緒依客戶的套接字建立輸入資料流in和輸資料流out。線程利用in讀取客戶放入線路裡的資訊。如果接受的訊息是“結束”,則伺服器回覆“結束”後關閉套接字連接;否則回覆:“我是伺服器你對我說“,以及伺服器接收到的訊息。
import java.net.*;import java.io.*;import java.awt.*;import javax.swing.*;import java.awt.event.*;import java.applet.*;public class Aclient extends Applet implements Runnable,ActionListener{ JButton button; JTextField textF; JTextArea textA; Socket socket; Thread thread; DataInputStream in; DataOutputStream out; public void init(){ setBackground(new Color(120,153,137)); setLayout(new BorderLayout()); Button = new JButton(“傳送訊息”); textF = new JTextFiel ; textA = new JTextArea(20,30); setSize(450,350); JPanel p = new JPanel(); p.add(textF); p.add(button); add(textA,”Center”); add(p,”South”); button.addActionListener(this ); } public void start(){ try{ socket = new Socket(this.getCodeBase().getHost(),4441); in = new DataInputStream(socket.getInputStream()); out = new DataOutputStream(socket.getOutputStream()); }catch(IOException e){} if(socket.getOutputStream()); }catch(IOException e){} if(ththread ==null){ thread = new Thread(this); thread.setPriority(Thread.MIN_PRIORITY); thread.start(); } } public void run(){ String s = null; while(true){ try{ s = in.readUTF(); }catch(IOException e){ } if(s.equals(“結束”)){ try{ socket.close();break; }catch(IOException e){} }else texA.append(s + “/n”); } } public void actionPerformed(ActionEvent e){ if(e.getSource()==button){ String s = textF.getText(); if (s! = null){ try{ out.writeUTF(s); }catch(IOException e1){} } else{ try{ out.writeUTF(“請說”); }catch(IOException e1){} } } }}