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

Java Socket 網絡編程入門:TCP/UDP 核心原理與實戰

     編輯:Java 相關知識

TCP/IP 協議族速覽

TCP/IP 是互聯網基石,分層模型:

  • IP 協議:無連接、不可靠、盡力而為的數據報投遞,基於 IP 地址路由。
  • TCP 協議:面向連接、可靠、有序、流控制,在 IP 基礎上增加端口、序列號、確認重傳機制。
  • UDP 協議:無連接、不可靠、數據報文、僅在 IP 基礎上增加端口複用,開銷極小。

Java 網絡編程核心類

類協議角色關鍵方法
ServerSocketTCP服務端監聽accept()、bind()、setSoTimeout()
SocketTCP客戶端/服務端連接getInputStream()、getOutputStream()、close()
DatagramSocketUDP發送/接收數據報send()、receive()、setSoTimeout()
DatagramPacketUDP數據報容器getData()、getAddress()、getPort()
InetAddress通用IP 地址封裝getByName()、getLocalHost()、getHostAddress()

獲取本機網絡接口信息

public static void printNetworkInterfaces() throws SocketException {
    Enumeration<NetworkInterface> interfaces = NetworkInterface.getNetworkInterfaces();
    while (interfaces.hasMoreElements()) {
        NetworkInterface ni = interfaces.nextElement();
        System.out.println("Interface: " + ni.getName() + " (" + ni.getDisplayName() + ")");
        Enumeration<InetAddress> addrs = ni.getInetAddresses();
        while (addrs.hasMoreElements()) {
            InetAddress addr = addrs.nextElement();
            System.out.println("  IP: " + addr.getHostAddress() + " [" + (addr.isLoopbackAddress() ? "Loopback" : "") + "]");
        }
    }
}

TCP Echo 客戶端/服務端完整實現

服務端

public class TcpEchoServer {
    private static final int PORT = 7;
    private static final int BUF_SIZE = 1024;

    public static void main(String[] args) throws IOException {
        try (ServerSocket server = new ServerSocket(PORT)) {
            server.setSoTimeout(0); // 永不超時
            System.out.println("TCP Echo Server 啟動,端口: " + PORT);
            while (true) {
                try (Socket client = server.accept()) {
                    System.out.println("客戶端連接: " + client.getRemoteSocketAddress());
                    try (InputStream in = client.getInputStream();
                         OutputStream out = client.getOutputStream()) {
                        byte[] buf = new byte[BUF_SIZE];
                        int len;
                        while ((len = in.read(buf)) != -1) {
                            out.write(buf, 0, len); // 原樣返回
                        }
                    }
                } catch (IOException e) {
                    System.err.println("客戶端處理異常: " + e.getMessage());
                }
            }
        }
    }
}

客戶端

public class TcpEchoClient {
    public static void main(String[] args) throws IOException {
        if (args.length < 2) {
            System.err.println("用法: java TcpEchoClient  ");
            return;
        }
        String host = args[0];
        byte[] data = args[1].getBytes(StandardCharsets.UTF_8);
        int port = 7;

        try (Socket socket = new Socket(host, port);
             InputStream in = socket.getInputStream();
             OutputStream out = socket.getOutputStream()) {

            System.out.println("已連接到 " + host + ":" + port);
            out.write(data);
            out.flush();

            byte[] buf = new byte[data.length];
            int total = 0, read;
            while (total < data.length && (read = in.read(buf, total, data.length - total)) != -1) {
                total += read;
            }
            System.out.println("服務端回傳: " + new String(buf, 0, total, StandardCharsets.UTF_8));
        }
    }
}

UDP Echo 客戶端/服務端完整實現

服務端

public class UdpEchoServer {
    private static final int PORT = 7;
    private static final int MAX_PACKET = 65507; // UDP 最大負載

    public static void main(String[] args) throws IOException {
        try (DatagramSocket socket = new DatagramSocket(PORT)) {
            byte[] buf = new byte[MAX_PACKET];
            DatagramPacket packet = new DatagramPacket(buf, buf.length);
            System.out.println("UDP Echo Server 啟動,端口: " + PORT);
            while (true) {
                socket.receive(packet); // 阻塞等待
                System.out.println("收到來自 " + packet.getAddress() + ":" + packet.getPort() + " 的數據");
                socket.send(packet); // 原樣發回
                packet.setLength(buf.length); // 重置長度供下次接收
            }
        }
    }
}

客戶端

public class UdpEchoClient {
    public static void main(String[] args) throws IOException {
        if (args.length < 2) {
            System.err.println("用法: java UdpEchoClient  ");
            return;
        }
        InetAddress serverAddr = InetAddress.getByName(args[0]);
        byte[] data = args[1].getBytes(StandardCharsets.UTF_8);
        int port = 7;

        try (DatagramSocket socket = new DatagramSocket()) {
            socket.setSoTimeout(3000); // 3秒超時
            DatagramPacket sendPkt = new DatagramPacket(data, data.length, serverAddr, port);
            DatagramPacket recvPkt = new DatagramPacket(new byte[data.length], data.length);

            int retries = 0;
            boolean received = false;
            while (!received && retries < 5) {
                socket.send(sendPkt);
                try {
                    socket.receive(recvPkt);
                    if (!recvPkt.getAddress().equals(serverAddr)) {
                        throw new IOException("未知來源回復");
                    }
                    received = true;
                    System.out.println("服務端回傳: " + new String(recvPkt.getData(), 0, recvPkt.getLength()));
                } catch (SocketTimeoutException e) {
                    retries++;
                    System.out.println("超時,重試 " + retries + "/5");
                }
            }
            if (!received) System.out.println("最終無響應");
        }
    }
}

TCP vs UDP 關鍵差異總結

維度TCPUDP
連接建立三次握手無連接
可靠性序列號+ACK+重傳,保證到達不可靠,可能丟包、亂序、重複
有序性保證順序無序
流控/擁塞控制滑動窗口、慢啟動、快速恢復無
邊界字節流,無消息邊界數據報,保留邊界
最大傳輸單元無上限(流控窗口)65507 字節(IPv4)
適用場景HTTP、數據庫、文件傳輸、郵件DNS、視頻會議、即時遊戲、廣播、IoT

實戰注意事項

  1. TCP 粘包/拆包:應用層需自定義協議(定長、分隔符、長度前綴)劃分消息邊界。
  2. UDP 丟包處理:業務層實現 ACK/重傳/幂等,或接受丟包(如視頻流)。
  3. 緩衝區大小:Socket.setReceiveBufferSize()/setSendBufferSize() 調優吞吐。
  4. 超時設置:setSoTimeout() 防止無限阻塞,setSoKeepAlive() 檢測死連接。
  5. NIO 升級:高併發場景使用 Selector + ServerSocketChannel/SocketChannel/DatagramChannel 實現非阻塞多路複用。

總結

Socket 是網絡編程基石。TCP 提供可靠字節流,適合強一致性場景;UDP 提供輕量數據報,適合高實時、容忍丟包場景。掌握阻塞 I/O 基礎後,進階學習 NIO、Netty、gRPC 等高性能框架,構建生產級網絡應用。

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