Java 教程

Java 控制語句

面向物件程式設計

Java 內建類

Java 檔案處理

Java 錯誤和異常

Java 多執行緒

Java 同步

Java 網路

Java 集合

Java 介面

Java 資料結構

Java 集合演算法

高階 Java

Java 雜項

Java API 和框架

Java 類參考

Java 有用資源

Java - 套接字程式設計



Java 中的套接字程式設計

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

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

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

Java 中套接字程式設計的步驟

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

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

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

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

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

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

建立連線後,可以使用 I/O 流進行通訊。每個套接字都具有 OutputStream 和 InputStream。客戶端的 OutputStream 連線到伺服器的 InputStream,而客戶端的 InputStream 連線到伺服器的 OutputStream。TCP 是一種雙向通訊協議,因此資料可以同時透過這兩個流傳送。

Java 套接字程式設計的優點

  • 平臺獨立性 - Java 套接字的最大優點之一是它們是平臺獨立的。這意味著相同的 Java 程式碼可以在多個作業系統和裝置上執行,無需修改。這使得跨不同系統輕鬆部署基於網路的應用程式,並確保應用程式可以在不同的裝置上執行,而無需平臺特定的程式碼。

  • 易於使用 - Java 套接字也相對易於使用,即使對於網路程式設計新手也是如此。Java API 提供了一個簡單一致的介面來建立和管理套接字,這使得輕鬆實現基於網路的應用程式,而無需瞭解底層網路協議。

  • 可擴充套件性 - Java 套接字具有高度可擴充套件性,使其適用於大型基於網路的應用程式。它們可以輕鬆處理數千個同時連線,並且可用於建立能夠處理高流量的分散式系統。

  • 安全性 - Java 套接字提供對安全通訊的內建支援,包括 SSL 和 TLS 加密。這使得輕鬆建立安全的基於網路的應用程式,並確保敏感資料在傳輸過程中得到保護。

  • 多執行緒 - Java 套接字支援多執行緒,這意味著多個執行緒可以同時處理多個連線。這提高了基於網路的應用程式的效能,並允許它們處理大量請求而不會過載。

Java 套接字程式設計的缺點

  • 複雜性 - 雖然 Java 套接字相對易於使用,但它們在實現時仍然可能很複雜,特別是對於網路程式設計新手而言。這種複雜性可能使除錯和排除基於網路的應用程式的故障變得困難,這可能既費時又令人沮喪。

  • 延遲 - Java 套接字可能會導致基於網路的應用程式出現延遲,尤其是在處理大量資料時。對於需要即時通訊的應用程式(例如線上遊戲或視訊會議),這可能是一個問題。

  • 資源密集型 - Java 套接字可能是資源密集型的,尤其是在處理大量連線或大量資料時。對於資源有限的系統(例如移動裝置或嵌入式系統),這可能是一個問題。

  • 協議支援有限 - Java 套接字支援有限數量的網路協議,這對於某些型別的基於網路的應用程式來說可能是一個限制。這可能使建立需要使用專有協議與其他系統通訊的應用程式變得困難。

  • 潛在的安全漏洞 - 與任何基於網路的應用程式一樣,Java 套接字容易受到安全威脅,例如駭客攻擊和中間人攻擊。在設計和實現基於 Java 套接字的系統時,必須注意安全性,以確保敏感資料得到保護,並識別和解決潛在的漏洞。

套接字程式設計應用程式

  • 聊天應用程式 − Java 套接字常用於建立聊天應用程式,例如即時訊息程式和線上聊天室。這些型別的應用程式通常使用客戶端-伺服器架構,其中客戶端連線到中央伺服器以傳送和接收訊息。

  • 檔案傳輸應用程式 − Java 套接字也可用於建立檔案傳輸應用程式,例如對等檔案共享程式。這些型別的應用程式使用對等架構,其中每個裝置既充當客戶端又充當伺服器。這允許裝置之間直接通訊,從而可以提高檔案傳輸的速度和可靠性。

  • 遠端控制應用程式 − Java 套接字也可用於建立遠端控制應用程式,例如遠端桌面軟體。這些型別的應用程式使用客戶端-伺服器架構,其中客戶端連線到遠端伺服器以控制伺服器的桌面。這允許使用者從任何具有網際網路連線的裝置訪問和控制其桌面。

  • 多人遊戲 − Java 套接字也常用於建立多人遊戲,例如線上角色扮演遊戲和第一人稱射擊遊戲。這些型別的應用程式通常使用客戶端-伺服器架構,其中客戶端連線到中央伺服器以玩遊戲。伺服器充當客戶端之間的中介,處理通訊和遊戲邏輯。

  • 物聯網應用 − Java 套接字也可用於物聯網 (IoT) 應用程式,例如智慧家居系統。這些型別的應用程式使用客戶端-伺服器架構,其中物聯網裝置連線到中央伺服器以傳送和接收資料。這允許遠端監控和控制裝置,以及資料收集和分析。

套接字程式設計示例

示例:套接字客戶端

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

// 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();
      }
   }
}

示例:套接字伺服器

以下 GreetingServer 程式是一個伺服器應用程式示例,它使用 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!
廣告