Java知多少(105)套接字(Socket)

網絡應用模式主要有:html

  • 主機/終端模式:集中計算,集中管理;
  • 客戶機/服務器(Client/Server,簡稱C/S)模式:分佈計算,分佈管理;
  • 瀏覽器/服務器模式:利用Internet跨平臺。


www(萬維網)就是創建在客戶機/服務器模式上,以HTML語言和HTTP協議爲基礎,可以提供各類Internet服務的信息瀏覽系統。網絡信息放在主機的不一樣位置,www服務器利用超文本鏈路連接各項信息。www客戶機(瀏覽器Brower)負責與服務器創建聯繫,向服務器發送請求,處理HTML超媒體,提供圖形用戶界面(GUI),顯示信息等。

在客戶機/服務器工做模式中,在Server端,要準備接受多個Client端計算機的通訊。爲此,除用IP地址標識Internet上的計算機以外,另還引入端口號,用端口號標識正在Server端後臺服務的線程。端口號與IP地址的組合稱爲網絡套接字(socket)。

Java語言在實現C/S模式中,套接字分爲兩類:java

  • 在Server端,ServerSocket類支持底層的網絡通訊;
  • 在Client端,Socket類支持網絡的底層通訊。

Server機經過端口(總線I/O地址)提供面向Client機的服務;Server機在它的幾個不一樣端口分別同時提供幾種不一樣的服務。Client接入Server的某一端口,經過這個端口提請Server機爲其服務。規定:端口號0~1023供系統專用。例如,HTTP協議在端口80,telnet協議在端口23。端口1024~65535供應用程序使用。

當Client程序和Server程序須要通訊時,能夠用Socket類創建套接字鏈接。套接字鏈接可想象爲一個電話呼叫:最初是Client程序創建呼叫,Server程序監聽;呼叫完成後,任何一方均可以隨時講話。

雙方實現通訊有流式socket和數據報式socket兩種可選方式:編程

  • 流式socket是有鏈接的通訊,即TCP(Transmission Control Protocol):每次通訊前創建鏈接,通訊結束後斷開鏈接。特色是能夠保證傳輸的正確性、可靠性。
  • 數據報式socket是無鏈接的通訊,即UDP(User Datagram Protocol):將欲傳輸的數據分紅 小包,直接上網發送。無需創建鏈接和拆除鏈接,速度快,但無可靠保證。


流式socket在Client程序和Server程序間創建通訊的通道。每一個socket能夠進行讀和寫兩種操做。對於任一端,與對方的通訊會話過程是:
創建socket鏈接,得到輸入/輸出流,讀數據/寫數據,通訊完成後關閉socket(拆除鏈接)。流式Socket的通訊過程見【例 13-1】。

利用socket的構造方法,能夠在客戶端創建到服務器的套接字對象:
    Socket(String host,int port):host是服務器的IP地址,port是端口號,這些是預先約定的。
例如,代碼:瀏覽器

1     try{
2         Socket mySocket = new Socket(「http://www.weixueyuan.net」 ,1860);
3     }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的信息。如如下代碼所示:app

    try{
        Socket sc = serverSocket.accept();//ac是一個Socket對象
    }catch(IOException e){}
要撤銷服務,能夠關閉Socket對象sc:
    sc.close();

【例 13-3】C/S模式中的Client端應用程序。這是一個Client端的流式Socket通訊的簡單實例,代碼說明Client端程序的編寫方法。例中,Client程序向服務器主機的端口4441提出請求,鏈接創建後完成對服務器的讀寫框架

 1 import java.io.*;
 2 import java.net.*;
 3 public class Client{
 4     public static void main(String args[]){
 5         String s = null;Socket mySocket;
 6         DataInputStream in = null;DataOutputStream out = null;
 7         try{
 8             mySocket = new Socket(「localhost」,4441);
 9             in = new DataInputStream(mySocket.getInputStream());
10             out = new DataOutputStream(mySocket.getOutputStream());
11             out.writeUTF(「good server!」);
12             while(true){
13                 s = in.readUTF();
14                 if(s==null) break;
15                 else System.out.println(s);
16             }
17             mySocket.close();
18         }catch(IOException e){
19             System.out.println(「can’t connect」);
20         }
21     }
22 }

【例 13-4】與例10.3 Client端應用程序對應的Server端應用程序。程序在4441端口監聽,當檢測到有客戶機請求時,產生一個內爲「客戶,你好,我是服務器」的字符串輸出到客戶端socket

 1 import java.io.*;import java.net.*;
 2 public class Server{
 3     public static void main(String args[]){
 4         ServerSocket server = null;
 5         Socket you = null;String s = null;
 6         DataOutputStream out = null;
 7         DataInputStream in = null;
 8         try{
 9             server = new ServerSocket(4441);
10         }catch(IOException e1){
11             system.out.println(「ERROR:」 +e1);
12         }
13         try{
14             you = server.accept();
15             in = new DataInputStream(you.getInputStream());
16             out = new DataOutputStream(you. getOutputStream());
17             while(true){
18                 s = in.readUTF();
19                 if(s!=null) break;
20             }
21             out.writeUTF(「客戶,你好,我是服務器」);
22             out.close();
23         }
24         catch(IOException e){System.out.println(「ERROR:」+e);}
25     }
26 }

爲了充分發揮計算機的平行工做能力,能夠把套接字鏈接工做讓一個線程完成。當客戶端要請求服務器給予服務,或當服務器端接收到一個客戶的服務請求,就啓動一個專門完成信息通訊的線程,在該線程中建立輸入輸出流,並完成客戶端與服務器端的信息交流。佈局


【例 13-5】 將套接字鏈接工做置於線程的客戶端小應用程序。界面在有一個發送信息按紐、一個文本框和一個文本區。客戶端應用程序首先與服務器創建套接字鏈接。使用數據輸入流in反覆讀取服務器放入線路里的信息,將收到的信息在文本區中顯示。婐志取的信息是「結束」,則關閉套接字鏈接,並結束程序。用戶也可在文本框輸入信息,並按發送信息按鈕,則客戶端程序利用數據輸出流out,將文本框中的內容發送給服務器。

 1 import java.net.*;
 2 import java.io.*;
 3 import java.awt.*;
 4 import javax.swing.*;
 5 import java.awt.event.*;
 6 import java.applet.*;
 7 public class Aclient extends Applet implements Runnable,ActionListener{
 8     JButton button; JTextField textF; JTextArea textA;
 9     Socket socket; Thread thread;
10     DataInputStream in; DataOutputStream out;
11     public void init(){
12         setBackground(new Color(120,153,137));
13         setLayout(new BorderLayout());
14         Button = new JButton(「發送信息」);
15         textF = new JTextField(20);
16         textA = new JTextArea(20,30);
17         setSize(450,350);
18         JPanel p = new JPanel();
19         p.add(textF); p.add(button);
20         add(textA,」Center」); add(p,」South」);
21         button.addActionListener(this);
22     }
23     public void start(){
24         try{
25             socket = new Socket(this.getCodeBase().getHost(),4441);
26             in = new DataInputStream(socket.getInputStream());
27             out = new DataOutputStream(socket.getOutputStream());
28         }catch(IOException e){}
29         if(thread==null){
30             thread = new Thread(this);
31             thread.setPriority(Thread.MIN_PRIORITY);
32             thread.start();
33         }
34     }
35     public void run(){
36         String s = null;
37         while(true){
38             try{
39                 s = in.readUTF();
40             }catch(IOException e){}
41             if(s.equals(「結束」)){
42                 try{
43                     socket.close();break;
44                 }catch(IOException e){}
45             }else texA.append(s + 「\n」);
46         }
47     }
48     public void actionPerformed(ActionEvent e){
49         if(e.getSource()==button){
50             String s = textF.getText();
51             if(s! = null){
52                 try{
53                     out.writeUTF(s);
54                 }catch(IOException e1){}
55             }
56             else{
57                 try{
58                     out.writeUTF(「請說話」);
59                 }
60                 catch(IOException e1){}
61             }
62         }
63     }
64 }

【例 13-6】對應例10.5客戶端小應用程序的服務器端小應用程序。程序以端4441創建與客戶端的套接字鏈接,服務器端收到客戶端的申請後,以客戶的套接字創建一個線程,並啓動。若是沒有客戶申請,則繼續監聽客戶的申請。線程按客戶的套接字創建輸入數據流in和輸數據流out。線程利用in讀取客戶放入線路里的信息。若是接受的信息是「結束」,則服務器回覆「結束」後關閉套接字鏈接;不然回覆:「我是服務器你對我說「,以及服務器接收到的信息

 1 import java.net.*;
 2 import java.io.*;
 3 import java.awt.*;
 4 import javax.swing.*;
 5 import java.awt.event.*;
 6 import java.applet.*;
 7 public class Aclient extends Applet implements Runnable,ActionListener{
 8     JButton button; JTextField textF; JTextArea textA;
 9     Socket socket; Thread thread;
10     DataInputStream in; DataOutputStream out;
11     public void init(){
12         setBackground(new Color(120,153,137));
13         setLayout(new BorderLayout());
14         Button = new JButton(「發送信息」);
15         textF = new JTextField(20);
16         textA = new JTextArea(20,30);
17         setSize(450,350);
18         JPanel p = new JPanel();
19         p.add(textF); p.add(button);
20         add(textA,」Center」); add(p,」South」);
21         button.addActionListener(this);
22     }
23     public void start(){
24         try{
25             socket = new Socket(this.getCodeBase().getHost(),4441);
26             in = new DataInputStream(socket.getInputStream());
27             out = new DataOutputStream(socket.getOutputStream());
28         }catch(IOException e){}
29         if(thread==null){
30             thread = new Thread(this);
31             thread.setPriority(Thread.MIN_PRIORITY);
32             thread.start();
33         }
34     }
35     public void run(){
36         String s = null;
37         while(true){
38              try{
39                 s = in.readUTF();
40             }catch(IOException e){}
41             if(s.equals(「結束」)){
42                 try{
43                     socket.close();break;
44                 }catch(IOException e){}
45             }else texA.append(s + 「\n」);
46         }
47     }
48     public void actionPerformed(ActionEvent e){
49         if(e.getSource()==button){
50             String s = textF.getText();
51             if(s! = null){
52                 try{
53                     out.writeUTF(s);
54                 }catch(IOException e1){}
55             }
56             else{
57                 try{
58                     out.writeUTF(「請說話」);
59                 }catch(IOException e1){}
60             }
61        }
62     }
63 }

系列文章:

相關文章
相關標籤/搜索