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

Java Socket 程式設計全攻略:TCP 可靠流與 UDP 資料包實戰完整範例

     編輯:Java 綜合教學

Socket 核心概念

  • Socket (套接字):IP 位址 + 埠號的封裝,網路通訊端點
  • 雙向通訊:雙方各有 Socket,透過 I/O 流/資料包交換資料
  • C/S 模型:Server 監聽埠,Client 主動連線,一 Server 可服務多 Client

TCP Socket 程式設計 (可靠、有序、面向連線)

伺服端步驟

  1. ServerSocket server = new ServerSocket(port) 綁定監聽
  2. Socket client = server.accept() 阻塞等待連線,回傳新 Socket
  3. 取得串流:client.getInputStream() / client.getOutputStream()
  4. 讀寫資料 (建議包裝 BufferedReader/PrintWriter)
  5. 關閉資源 (finally 區塊或 try-with-resources)

客戶端步驟

  1. Socket socket = new Socket(host, port) 主動連線
  2. 取得串流,讀寫資料
  3. 關閉資源

完整實戰範例:大寫轉換伺服器

// TCPServer.java
public class TCPServer {
    public static void main(String[] args) throws IOException {
        try (ServerSocket server = new ServerSocket(8888)) {
            System.out.println("Server 啟動,監聽 8888...");
            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 clientIp = client.getInetAddress().getHostAddress();
                    System.out.println(clientIp + " 連線成功");
                    
                    String line;
                    while ((line = in.readLine()) != null) {
                        if ("over".equalsIgnoreCase(line)) break;
                        System.out.println("收到: " + line);
                        out.println(line.toUpperCase()); // 回傳大寫
                    }
                    System.out.println(clientIp + " 斷開連線");
                } catch (IOException e) {
                    System.err.println("客戶端處理異常: " + e.getMessage());
                }
            }
        }
    }
}
// TCPClient.java
public class TCPClient {
    public static void main(String[] args) throws IOException {
        try (Socket socket = new Socket("127.0.0.1", 8888);
             BufferedReader keyboard = new BufferedReader(new InputStreamReader(System.in));
             PrintWriter out = new PrintWriter(new OutputStreamWriter(socket.getOutputStream(), StandardCharsets.UTF_8), true);
             BufferedReader in = new BufferedReader(new InputStreamReader(socket.getInputStream(), StandardCharsets.UTF_8))) {
            
            System.out.println("已連線至伺服器,輸入 'over' 結束");
            String line;
            while ((line = keyboard.readLine()) != null) {
                out.println(line);
                if ("over".equalsIgnoreCase(line)) break;
                System.out.println("伺服器回應: " + in.readLine());
            }
        }
    }
}

編譯執行指令

# 終端機 1: 啟動伺服器
javac TCPServer.java && java TCPServer

# 終端機 2: 啟動客戶端
javac TCPClient.java && java TCPClient

UDP Socket 程式設計 (不可靠、無序、無連線、低延遲)

核心類別

  • DatagramSocket:發送/接收端點,綁定本地埠
  • DatagramPacket:資料包封裝 (資料緩衝區、長度、目標 IP/埠、來源 IP/埠)

發送端步驟

  1. DatagramSocket socket = new DatagramSocket() (系統自動分配本地埠)
  2. 建立封包:new DatagramPacket(data, length, InetAddress.getByName(host), port)
  3. socket.send(packet)
  4. 關閉 Socket

接收端步驟

  1. DatagramSocket socket = new DatagramSocket(port) 綁定監聽埠
  2. 準備緩衝區:byte[] buf = new byte[1024]
  3. 建立空封包:DatagramPacket packet = new DatagramPacket(buf, buf.length)
  4. socket.receive(packet) 阻塞接收
  5. 解析:packet.getData()、packet.getLength()、packet.getAddress()、packet.getPort()
  6. 關閉 Socket

完整實戰範例:雙向回應

// UDPSender.java
public class UDPSender {
    public static void main(String[] args) throws IOException {
        try (DatagramSocket socket = new DatagramSocket()) {
            String msg = "I love you";
            byte[] data = msg.getBytes(StandardCharsets.UTF_8);
            
            // 發送
            DatagramPacket sendPacket = new DatagramPacket(data, data.length, InetAddress.getByName("localhost"), 6666);
            socket.send(sendPacket);
            System.out.println("已發送: " + msg);
            
            // 接收回應
            byte[] buf = new byte[1024];
            DatagramPacket recvPacket = new DatagramPacket(buf, buf.length);
            socket.receive(recvPacket);
            String reply = new String(recvPacket.getData(), 0, recvPacket.getLength(), StandardCharsets.UTF_8);
            System.out.println("收到回應: " + reply);
        }
    }
}
// UDPReceiver.java
public class UDPReceiver {
    public static void main(String[] args) throws IOException {
        try (DatagramSocket socket = new DatagramSocket(6666)) {
            System.out.println("Receiver 啟動,監聽 6666...");
            
            byte[] buf = new byte[1024];
            DatagramPacket packet = new DatagramPacket(buf, buf.length);
            socket.receive(packet); // 阻塞等待
            
            String received = new String(packet.getData(), 0, packet.getLength(), StandardCharsets.UTF_8);
            System.out.println("收到: " + received + " from " + packet.getAddress() + ":" + packet.getPort());
            
            // 回應
            String reply = "Me too";
            byte[] replyData = reply.getBytes(StandardCharsets.UTF_8);
            DatagramPacket replyPacket = new DatagramPacket(replyData, replyData.length, packet.getAddress(), packet.getPort());
            socket.send(replyPacket);
            System.out.println("已回應: " + reply);
        }
    }
}

編譯執行 (先啟動接收端)

# 終端機 1
javac UDPReceiver.java && java UDPReceiver

# 終端機 2
javac UDPSender.java && java UDPSender

TCP vs UDP 選型指南

維度TCPUDP
可靠性保證送達、重傳、排序不保證,可能丟包/亂序/重複
連線建立三次交握 (延遲)無連線,即發即走
流量控制滑動視窗、阻塞控制無,應用層自行控制
資料單位位元組流 (無邊界)資料包 (保留邊界)
適用場景HTTP、DB、郵件、檔案傳輸、即時通訊核心直播、VoIP、遊戲同步、DNS、SNMP、廣播
Java 類別Socket / ServerSocketDatagramSocket / DatagramPacket

進階提示

  • TCP 粘包/拆包:串流無邊界,應用層需自訂協定 (長度前綴、分隔符、固定長度)
  • NIO / Netty:高併發場景請使用非阻塞 I/O (NIO) 或 Netty 框架,避免一執行緒一連線模型瓶頸
  • UDP 可靠性補強:應用層實作 ACK/重傳/序號 (如 QUIC、KCP、RUDP)
  • 資源管理:務必使用 try-with-resources 確保 Socket 關閉,避免檔案描述符洩漏
  1. 上一篇文章:
  2. 下一篇文章:
Copyright © 程式碼之家 All Rights Reserved