Java 教程

Java 控制語句

面向物件程式設計

Java 內建類

Java 檔案處理

Java 錯誤和異常

Java 多執行緒

Java 同步

Java 網路程式設計

Java 集合

Java 介面

Java 資料結構

Java 集合演算法

高階 Java

Java 其他

Java APIs 和框架

Java 類引用

Java 有用資源

Java - 網路程式設計



Java 網路程式設計

Java 網路程式設計 指的是編寫在多個裝置(計算機)上執行的程式,這些裝置透過網路相互連線。

Java 網路程式設計的優勢

  • 建立伺服器-客戶端應用程式
  • 實現網路協議
  • 實現套接字程式設計
  • 建立 Web 服務

網路程式設計中使用的包

J2SE API 的 java.net 包包含一系列類和介面,它們提供了底層的通訊細節,允許您編寫專注於解決問題的程式。

java.net 包為兩種常見的網路協議提供支援:

  • TCP − TCP 代表傳輸控制協議,它允許兩個應用程式之間進行可靠的通訊。TCP 通常用於網際網路協議之上,稱為 TCP/IP。

  • UDP − UDP 代表使用者資料報協議,這是一種無連線的協議,允許在應用程式之間傳輸資料包。

本章對以下兩個主題進行了很好的講解:

  • 套接字程式設計 − 這是網路程式設計中最常用的概念,已進行詳細解釋。

  • URL 處理 − 這將在單獨章節中介紹。點選此處瞭解 Java 語言中的URL 處理

Java 網路程式設計中的套接字程式設計

套接字使用 TCP 提供兩臺計算機之間的通訊機制。客戶端程式在其通訊端建立一個套接字,並嘗試將該套接字連線到伺服器。

建立連線後,伺服器在其通訊端建立一個套接字物件。客戶端和伺服器現在可以透過寫入和讀取套接字進行通訊。

java.net.Socket 類表示套接字,java.net.ServerSocket 類為伺服器程式提供了一種機制,用於監聽客戶端並與之建立連線。

使用套接字在兩臺計算機之間建立 TCP 連線時,會發生以下步驟:

  • 伺服器例項化一個 ServerSocket 物件,表示要進行通訊的埠號。

  • 伺服器呼叫 ServerSocket 類的 accept() 方法。此方法一直等到客戶端連線到給定埠上的伺服器。

  • 伺服器等待後,客戶端例項化一個 Socket 物件,指定要連線到的伺服器名稱和埠號。

  • Socket 類的建構函式嘗試將客戶端連線到指定的伺服器和埠號。如果建立了通訊,則客戶端現在擁有一個能夠與伺服器通訊的 Socket 物件。

  • 在伺服器端,accept() 方法返回對伺服器上連線到客戶端套接字的新套接字的引用。

建立連線後,可以使用 I/O 流進行通訊。每個套接字都有一個 OutputStream 和一個 InputStream。客戶端的 OutputStream 連線到伺服器的 InputStream,客戶端的 InputStream 連線到伺服器的 OutputStream。

TCP 是一種雙向通訊協議,因此資料可以同時透過兩個流傳送。以下是提供完整方法集以實現套接字的有用類。

ServerSocket 類建構函式

java.net.ServerSocket 類用於伺服器應用程式獲取埠並監聽客戶端請求。

ServerSocket 類有四個建構函式:

序號 方法和描述
1

public ServerSocket(int port) throws IOException

嘗試建立一個繫結到指定埠的伺服器套接字。如果埠已被其他應用程式繫結,則會發生異常。

2

public ServerSocket(int port, int backlog) throws IOException

與之前的建構函式類似,backlog 引數指定在等待佇列中儲存多少個傳入客戶端。

3

public ServerSocket(int port, int backlog, InetAddress address) throws IOException

與之前的建構函式類似,InetAddress 引數指定要繫結的本地 IP 地址。對於可能具有多個 IP 地址的伺服器,InetAddress 用於允許伺服器指定其哪個 IP 地址用於接受客戶端請求。

4

public ServerSocket() throws IOException

建立一個未繫結的伺服器套接字。使用此建構函式時,準備好繫結伺服器套接字後,請使用 bind() 方法。

如果 ServerSocket 建構函式沒有丟擲異常,則表示您的應用程式已成功繫結到指定的埠,並已準備好接受客戶端請求。

ServerSocket 類方法

以下是 ServerSocket 類的一些常用方法:

序號 方法和描述
1

public int getLocalPort()

返回伺服器套接字正在監聽的埠。如果您在建構函式中傳入 0 作為埠號並讓伺服器為您查詢埠,則此方法很有用。

2

public Socket accept() throws IOException

等待傳入客戶端。此方法會阻塞,直到客戶端連線到指定埠上的伺服器或套接字超時(假設已使用 setSoTimeout() 方法設定了超時值)。否則,此方法將無限期阻塞。

3

public void setSoTimeout(int timeout)

設定伺服器套接字在 accept() 期間等待客戶端的時間超時值。

4

public void bind(SocketAddress host, int backlog)

將套接字繫結到 SocketAddress 物件中指定的伺服器和埠。如果您使用無引數建構函式例項化了 ServerSocket,請使用此方法。

當 ServerSocket 呼叫 accept() 時,該方法在客戶端連線之前不會返回。客戶端連線後,ServerSocket 會在未指定的埠上建立一個新的 Socket,並返回對這個新 Socket 的引用。現在客戶端和伺服器之間存在 TCP 連線,可以開始通訊。

Socket 類建構函式

java.net.Socket 類表示客戶端和伺服器都用來彼此通訊的套接字。客戶端透過例項化一個 Socket 物件來獲取它,而伺服器則從 accept() 方法的返回值獲取 Socket 物件。

Socket 類有五個建構函式,客戶端可以使用它們來連線到伺服器:

序號 方法和描述
1

public Socket(String host, int port) throws UnknownHostException, IOException.

此方法嘗試連線到指定埠上的指定伺服器。如果此建構函式沒有丟擲異常,則連線成功,客戶端已連線到伺服器。

2

public Socket(InetAddress host, int port) throws IOException

此方法與之前的建構函式相同,只是主機由 InetAddress 物件表示。

3

public Socket(String host, int port, InetAddress localAddress, int localPort) throws IOException.

連線到指定的主機和埠,在本地主機上建立套接字,地址和埠由引數指定。

4

public Socket(InetAddress host, int port, InetAddress localAddress, int localPort) throws IOException.

此方法與之前的建構函式相同,只是主機由 InetAddress 物件而不是 String 表示。

5

public Socket()

建立一個未連線的套接字。使用 connect() 方法將此套接字連線到伺服器。

當 Socket 建構函式返回時,它不僅會例項化一個 Socket 物件,還會嘗試連線到指定的伺服器和埠。

Socket 類方法

這裡列出了一些 Socket 類中值得關注的方法。請注意,客戶端和伺服器都有一個 Socket 物件,因此這些方法可以由客戶端和伺服器呼叫。

序號 方法和描述
1

public void connect(SocketAddress host, int timeout) throws IOException

此方法將套接字連線到指定的主機。僅當您使用無引數建構函式例項化 Socket 時才需要此方法。

2

public InetAddress getInetAddress()

此方法返回此套接字連線到的另一臺計算機的地址。

3

public int getPort()

返回套接字在遠端計算機上繫結的埠。

4

public int getLocalPort()

返回套接字在本地計算機上繫結的埠。

5

public SocketAddress getRemoteSocketAddress()

返回遠端套接字的地址。

6

public InputStream getInputStream() throws IOException

返回套接字的輸入流。輸入流連線到遠端套接字的輸出流。

7

public OutputStream getOutputStream() throws IOException

返回套接字的輸出流。輸出流連線到遠端套接字的輸入流。

8

public void close() throws IOException

關閉套接字,這使得此 Socket 物件不再能夠連線到任何伺服器。

InetAddress 類方法

此類表示網際網路協議 (IP) 地址。以下是在進行套接字程式設計時可能需要的一些有用方法:

序號 方法和描述
1

static InetAddress getByAddress(byte[] addr)

給定原始 IP 地址,返回一個 InetAddress 物件。

2

static InetAddress getByAddress(String host, byte[] addr)

基於提供的主機名和 IP 地址建立 InetAddress。

3

static InetAddress getByName(String host)

根據主機名確定主機的 IP 地址。

4

String getHostAddress()

以文字形式返回 IP 地址字串。

5

String getHostName()

獲取此 IP 地址的主機名。

6

static InetAddress InetAddress getLocalHost()

返回本地主機。

7

String toString()

將此 IP 地址轉換為字串。

Java 網路程式設計示例

在 Java 中實現 Socket 客戶端

下面的 GreetingClient 是一個客戶端程式,它使用套接字連線到伺服器,傳送問候語,然後等待響應。

示例:Socket 客戶端

// File Name GreetingClient.java
import java.net.*;
import java.io.*;

public class GreetingClient {

   public static void main(String [] args) {
      String serverName = args[0];
      int port = Integer.parseInt(args[1]);
      try {
         System.out.println("Connecting to " + serverName + " on port " + port);
         Socket client = new Socket(serverName, port);
         
         System.out.println("Just connected to " + client.getRemoteSocketAddress());
         OutputStream outToServer = client.getOutputStream();
         DataOutputStream out = new DataOutputStream(outToServer);
         
         out.writeUTF("Hello from " + client.getLocalSocketAddress());
         InputStream inFromServer = client.getInputStream();
         DataInputStream in = new DataInputStream(inFromServer);
         
         System.out.println("Server says " + in.readUTF());
         client.close();
      } catch (IOException e) {
         e.printStackTrace();
      }
   }
}

在 Java 中實現 Socket 伺服器

下面的 GreetingServer 程式是一個伺服器應用程式示例,它使用 Socket 類監聽命令列引數指定的埠號上的客戶端:

示例:Socket 伺服器

// File Name GreetingServer.java
import java.net.*;
import java.io.*;

public class GreetingServer extends Thread {
   private ServerSocket serverSocket;
   
   public GreetingServer(int port) throws IOException {
      serverSocket = new ServerSocket(port);
      serverSocket.setSoTimeout(10000);
   }

   public void run() {
      while(true) {
         try {
            System.out.println("Waiting for client on port " + 
               serverSocket.getLocalPort() + "...");
            Socket server = serverSocket.accept();
            
            System.out.println("Just connected to " + server.getRemoteSocketAddress());
            DataInputStream in = new DataInputStream(server.getInputStream());
            
            System.out.println(in.readUTF());
            DataOutputStream out = new DataOutputStream(server.getOutputStream());
            out.writeUTF("Thank you for connecting to " + server.getLocalSocketAddress()
               + "\nGoodbye!");
            server.close();
            
         } catch (SocketTimeoutException s) {
            System.out.println("Socket timed out!");
            break;
         } catch (IOException e) {
            e.printStackTrace();
            break;
         }
      }
   }
   
   public static void main(String [] args) {
      int port = Integer.parseInt(args[0]);
      try {
         Thread t = new GreetingServer(port);
         t.start();
      } catch (IOException e) {
         e.printStackTrace();
      }
   }
}

編譯客戶端和伺服器,然後按如下方式啟動伺服器:

$ java GreetingServer 6066
Waiting for client on port 6066...

按如下方式檢查客戶端程式:

輸出

$ java GreetingClient localhost 6066
Connecting to localhost on port 6066
Just connected to localhost/127.0.0.1:6066
Server says Thank you for connecting to /127.0.0.1:6066
Goodbye!
廣告