首頁
編程語言
C語言|JAVA編程
Python編程
網頁編程
ASP編程|PHP編程
JSP編程
數據庫
MYSQL數據庫|SqlServer數據庫
Oracle數據庫|DB2數據庫
您现在的位置: 程式碼之家 >> 編程語言 >  >> Java 程式設計 >> Java 相關知識

Java Socket 程式設計入門 (一):從 OSI 模型理解 Socket 定位與 TCP/UDP 選型

     編輯:Java 相關知識

前言:為什麼要學 Socket?

Socket 是網路通訊的基礎抽象。無論你開發即時聊天、微服務 RPC、物聯網裝置通訊,底層都離不開 Socket。Java 在 java.net 封裝了平台差異,讓開發者專注於應用層協定設計,而非纏繞於作業系統底層的 bind/listen/epoll 細節。本系列將從概念模型、API 實戰、多執行緒/連線池進階、實戰案例四個維度循序漸進。

Socket 在網路分層模型中的位置

OSI 七層模型 vs TCP/IP 四層模型

OSI 七層TCP/IP 四層典型協定/技術Socket 位置
7. 應用層應用層HTTP, FTP, SMTP, DNS⬆ 應用程式邏輯
6. 表達層加密/壓縮/序列化 (SSL, JSON, Protobuf)
5. 會話層會話管理 (RPC 框架、WebSocket 握手)
4. 傳輸層傳輸層TCP, UDP🔌 Socket API 介面
3. 網路層網路層IP, ICMP, 路由⬇ 作業系統核心協定棧
2. 資料鏈路層資料鏈路層Ethernet, Wi-Fi, MAC
1. 實體層(合併)光纖、銅纜、電波

結論:Socket 位於會話層/傳輸層交界,向上為應用提供「可靠位元組流 (TCP)」或「不可靠資料報 (UDP)」的統一介面,向下屏蔽 IP 封包分片、重組、流控、重傳等複雜性。

什麼是 Socket?一個生活化比喻

「Socket 就像電話插座。你的程式是電話機,想跟遠端通話,必須插上插座 (建立 Socket)、撥號 (connect/bind)、建立專線 (TCP 連線)。通話過程中,你只管說話/聽聲音 (read/write),不需知道聲音如何轉為電訊號、經由交換機路由到對方。掛斷 (close) 後,線路釋放。」

  • IP + Port = 插座地址:IP 定位主機,Port 定位進程。
  • 雙向通道:建立連線後,雙方皆可收發,直到一方關閉。
  • 流式抽象:TCP Socket 表現為 InputStream/OutputStream,像讀寫檔案一樣自然。

Java Socket 兩大類型:TCP vs UDP

特性TCP Socket (Socket/ServerSocket)UDP Socket (DatagramSocket)
連線導向是 (三次交握、四次揮手)無 (無連線)
可靠性保證有序、不重複、不丟失不保證 (可能丟包、亂序、重複)
流量控制/擁塞控制內建 (滑動窗口、慢啟動)無 (應用層自行實作)
資料邊界無 (位元組流,需自行分幀)有 (每個 DatagramPacket 保留邊界)
適用場景Web、資料庫、訊息隊列、檔案傳輸、SSH即時音視訊、DNS、SNMP、遊戲狀態同步、廣播/多播
Java 核心類Socket, ServerSocketDatagramSocket, DatagramPacket

選型建議

  • 預設選 TCP:除非你有明確理由 (極低延遲、可容忍丟包、廣播需求),TCP 的可靠性讓應用層開發簡單得多。
  • UDP 需自建可靠層:若用 UDP 傳輸關鍵資料,必須在應用層實作序號、ACK、重傳、排序 (如 QUIC、RUDP),複雜度極高。

Java TCP Socket 核心 API 快速上手

伺服端

try (ServerSocket server = new ServerSocket(8080)) {
    System.out.println("Server listening on 8080...");
    while (true) {
        try (Socket client = server.accept();
             BufferedReader in = new BufferedReader(new InputStreamReader(client.getInputStream(), StandardCharsets.UTF_8));
             PrintWriter out = new PrintWriter(new OutputStreamWriter(client.getOutputStream(), StandardCharsets.UTF_8), true)) {
            
            String msg = in.readLine();
            System.out.println("Received: " + msg);
            out.println("Echo: " + msg);
        } catch (IOException e) {
            e.printStackTrace();
        }
    }
}

客戶端

try (Socket socket = new Socket("localhost", 8080);
     PrintWriter out = new PrintWriter(new OutputStreamWriter(socket.getOutputStream(), StandardCharsets.UTF_8), true);
     BufferedReader in = new BufferedReader(new InputStreamReader(socket.getInputStream(), StandardCharsets.UTF_8));
     BufferedReader console = new BufferedReader(new InputStreamReader(System.in))) {
    
    System.out.println("Connected. Type 'bye' to exit.");
    String line;
    while ((line = console.readLine()) != null) {
        out.println(line);
        System.out.println("Server: " + in.readLine());
        if ("bye".equalsIgnoreCase(line)) break;
    }
}

下一篇預告

下一篇將深入實戰:多執行緒伺服器架構 (Thread-per-Connection vs Thread Pool)、非阻塞 NIO 入門 (Selector, Channel, Buffer)、連線池與 Keep-Alive 管理、自訂協定編解碼 (Length-Prefix, Delimiter, Protobuf)。

  1. 上一篇文章:
  2. 下一篇文章:
Copyright © 程式碼之家 All Rights Reserved