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

Java 網絡編程核心總結:從 OSI 模型到 Socket 實戰

     編輯:Java 綜合教學

Java 網絡編程核心總結:從 OSI 模型到 Socket 實戰

網絡編程是 Java 開發中不可或缺的技能,本文系統梳理了網絡通信的理論基礎、核心 API 以及 UDP/TCP 兩種協議的實戰代碼,幫助開發者建立完整的知識體系。

一、網絡模型:通信的「通用語言」

計算機網絡通信遵循特定規則,這就是網絡模型。主流有兩種:

  • OSI 七層參考模型:理論標準,分為物理層、數據鏈路層、網絡層、傳輸層、會話層、表示層、應用層。
  • TCP/IP 四層模型:工事實標準,將 OSI 七層精簡為網絡接口層、網絡層、傳輸層、應用層。

OSI 七層核心職責速覽

層級核心功能數據單元典型設備/協議
物理層定義物理設備標準,傳輸比特流比特網線、光纖、中繼器
數據鏈路層MAC 地址封裝/解封裝幀交換機、網卡
網絡層IP 地址封裝/解封裝,路由選擇數據包路由器、IP 協議
傳輸層端口號、分段傳輸、重組,提供 TCP/UDP段TCP(可靠)、UDP(高效)
會話層建立/管理/終止會話數據RPC、SQL
表示層數據解釋、加密解密、壓縮解壓數據JPEG、MPEG、SSL
應用層終端用戶應用協議數據HTTP、FTP、DNS

二、網絡通信三要素

  1. IP 地址:設備在網絡中的唯一標識(如 192.168.1.1),Java 用 InetAddress 類操作。
  2. 端口號:標識進程的邏輯地址(0~65535),0~1023 為系統保留。
  3. 傳輸協議:通信規則,主流為 TCP(面向連接、可靠)和 UDP(無連接、高效)。

InetAddress 常用方法

// 獲取本機地址
InetAddress local = InetAddress.getLocalHost();
// 根據主機名/域名獲取地址
InetAddress remote = InetAddress.getByName("www.example.com");
// 獲取 IP 字符串
String ip = remote.getHostAddress();
// 獲取主機名
String host = remote.getHostName();

三、Socket 編程:網絡通信的基石

Socket = IP 地址 + 端口號,是網絡通信的端點。Java 提供 java.net.Socket (TCP) 和 java.net.DatagramSocket (UDP)。

UDP 通信:輕量級、無連接

核心類:DatagramSocket(發送/接收端)、DatagramPacket(數據包)。

發送端流程:創建 Socket → 封裝數據包(數據、長度、目標 IP、端口) → send() → 關閉資源。

接收端流程:創建 Socket(綁定端口) → 準備空數據包 → receive() 阻塞等待 → 解析數據包 → 關閉資源。

// 發送端示例
DatagramSocket ds = new DatagramSocket();
byte[] data = "Hello UDP".getBytes();
InetAddress addr = InetAddress.getByName("192.168.1.100");
DatagramPacket dp = new DatagramPacket(data, data.length, addr, 8888);
ds.send(dp);
ds.close();
// 接收端示例
DatagramSocket ds = new DatagramSocket(8888);
byte[] buf = new byte[1024];
DatagramPacket dp = new DatagramPacket(buf, buf.length);
ds.receive(dp); // 阻塞
String msg = new String(dp.getData(), 0, dp.getLength());
System.out.println("來自 " + dp.getAddress().getHostAddress() + ": " + msg);
ds.close();

進階:UDP 聊天室(多線程) —— 發送線程處理鍵盤輸入,接收線程循環監聽,實現雙向通信。

TCP 通信:可靠、面向連接

核心類:ServerSocket(服務端)、Socket(客戶端/服務端連接對象)。通過「三次握手」建立連接,形成輸入/輸出流通道。

客戶端流程:`new Socket(ip, port)` → 獲取輸出流寫數據 / 輸入流讀回應 → 關閉。

服務端流程:`new ServerSocket(port)` → `accept()` 阻塞等待連接 → 獲取客戶端 Socket 的流進行通信 → 處理完關閉客戶端 Socket(服務端 Socket 通常不關閉)。

// 客戶端發送文件並接收反饋(解決阻塞問題)
Socket s = new Socket("192.168.1.100", 9999);
BufferedInputStream bis = new BufferedInputStream(new FileInputStream("photo.jpg"));
BufferedOutputStream bos = new BufferedOutputStream(s.getOutputStream());
byte[] buf = new byte[1024];
int len;
while ((len = bis.read(buf)) != -1) bos.write(buf, 0, len);
bos.flush();
// 關鍵:通知服務端輸出流結束,避免雙方 read() 互相阻塞
s.shutdownOutput();
// 讀取服務端反饋
BufferedReader br = new BufferedReader(new InputStreamReader(s.getInputStream()));
System.out.println("服務端: " + br.readLine());
bis.close(); s.close();
// 服務端多線程處理上傳
ServerSocket ss = new ServerSocket(9999);
while (true) {
    Socket s = ss.accept();
    new Thread(() -> {
        try {
            BufferedInputStream bis = new BufferedInputStream(s.getInputStream());
            String fileName = System.currentTimeMillis() + ".jpg";
            BufferedOutputStream bos = new BufferedOutputStream(new FileOutputStream(fileName));
            byte[] buf = new byte[1024];
            int len;
            while ((len = bis.read(buf)) != -1) bos.write(buf, 0, len);
            bos.flush();
            // 反饋
            s.getOutputStream().write("上傳成功".getBytes());
            bos.close(); s.close();
        } catch (IOException e) { e.printStackTrace(); }
    }).start();
}

四、TCP 常見阻塞問題與解決

現象:雙方都在 `read()`/`readLine()` 等待,程序掛起。

原因:流無終結標記,接收方不知道發送方何時結束。

方案:

  1. 自定義結束標記(如 "over"),但不優雅。
  2. 推薦:發送方調用 socket.shutdownOutput(),接收方 `read()` 返回 -1,感知流結束。

五、總結

  • UDP 適合即時性要求高、容忍丟包的場景(視頻會議、直播、DNS 查詢)。
  • TCP 適合數據完整性關鍵的場景(文件傳輸、郵件、HTTP、數據庫連接)。
  • 實際開發中,多線程 + NIO (Netty) 是高性能網絡服務的主流選型。

OSI 七層模型圖解

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