在 Java 后端开发中,网络编程是核心技能之一 —— 无论是微服务间的通信、分布式系统的数据传输,还是简单的客户端 - 服务器交互,都离不开网络编程的支撑。本文从基础概念到实战代码,再到进阶技巧,带你全面掌握 Java 网络编程,新手也能跟着敲出可运行的 demo!​

一、基础核心:搞懂 Socket 与 TCP/UDP​

Java 网络编程的核心是Socket(套接字),它相当于通信的 "插座",负责在两个设备间建立数据传输的通道。而 Socket 通信主要依赖两种协议:TCP 和 UDP,先搞懂它们的区别,才能选对场景用对方案。​

特性​

TCP​

UDP​

连接方式​

面向连接(三次握手)​

无连接​

可靠性​

可靠(重传机制)​

不可靠(丢包风险)​

传输速度​

较慢​

较快​

适用场景​

文件传输、登录验证​

直播、游戏、DNS 查询​

关键 API:Java 对网络编程的支持主要在java.net包中,核心类包括:​

  • Socket:客户端套接字,用于发起连接​
  • ServerSocket:服务端套接字,用于监听连接​
  • DatagramSocket:UDP 通信的套接字​
  • DatagramPacket:UDP 传输的数据包载体​

二、实战代码:TCP/UDP 通信 demo(可直接运行)​

理论不如实践,下面用两个极简 demo,带你实现 TCP 和 UDP 的客户端 - 服务端通信,复制代码就能跑通!​

1. TCP 通信:可靠的客户端 - 服务端交互​

TCP 是面向连接的协议,需先建立服务端监听,再由客户端发起连接,适合需要可靠传输的场景(如用户登录)。​

服务端代码(Server)

import java.io.*;
import java.net.ServerSocket;
import java.net.Socket;

public class TcpServer {
    public static void main(String[] args) {
        // 1. 定义端口号(1024-65535之间,避免占用系统端口)
        int port = 8888;
        try (
            // 2. 创建服务端套接字,监听指定端口
            ServerSocket serverSocket = new ServerSocket(port);
            // 3. 等待客户端连接(阻塞方法,直到有客户端接入)
            Socket clientSocket = serverSocket.accept();
            // 4. 获取输入流,读取客户端消息
            BufferedReader in = new BufferedReader(
                new InputStreamReader(clientSocket.getInputStream()));
            // 5. 获取输出流,向客户端发送响应
            PrintWriter out = new PrintWriter(
                clientSocket.getOutputStream(), true);
        ) {
            System.out.println("客户端已连接:" + clientSocket.getInetAddress());
            // 6. 读取客户端消息
            String clientMsg = in.readLine();
            System.out.println("收到客户端消息:" + clientMsg);
            // 7. 向客户端发送响应
            out.println("服务端已收到:" + clientMsg);
        } catch (IOException e) {
            e.printStackTrace();
        }
    }
}

客户端代码(Client)

import java.io.*;
import java.net.Socket;

public class TcpClient {
    public static void main(String[] args) {
        // 1. 服务端IP(本地测试用127.0.0.1)和端口号
        String serverIp = "127.0.0.1";
        int serverPort = 8888;
        try (
            // 2. 创建客户端套接字,连接服务端
            Socket socket = new Socket(serverIp, serverPort);
            // 3. 获取输出流,向服务端发送消息
            PrintWriter out = new PrintWriter(
                socket.getOutputStream(), true);
            // 4. 获取输入流,读取服务端响应
            BufferedReader in = new BufferedReader(
                new InputStreamReader(socket.getInputStream()));
        ) {
            // 5. 向服务端发送消息
            out.println("Hello, TCP Server!");
            // 6. 读取服务端响应
            String serverMsg = in.readLine();
            System.out.println("收到服务端响应:" + serverMsg);
        } catch (IOException e) {
            e.printStackTrace();
        }
    }
}

运行步骤:先启动TcpServer,再启动TcpClient,客户端会打印服务端的响应,服务端会显示客户端的 IP 和消息。​

2. UDP 通信:无连接的快速传输​

UDP 无需建立连接,直接发送数据包,适合对速度要求高、可接受少量丢包的场景(如实时弹幕)。​

发送端代码(Sender)

import java.net.*;

public class UdpSender {
    public static void main(String[] args) {
        // 服务端IP和端口
        String serverIp = "127.0.0.1";
        int serverPort = 9999;
        try (
            // 创建UDP套接字
            DatagramSocket socket = new DatagramSocket();
        ) {
            // 1. 准备要发送的数据
            String msg = "Hello, UDP Receiver!";
            byte[] data = msg.getBytes();
            // 2. 创建数据包(数据、数据长度、目标IP、目标端口)
            DatagramPacket packet = new DatagramPacket(
                data, data.length, InetAddress.getByName(serverIp), serverPort);
            // 3. 发送数据包
            socket.send(packet);
            System.out.println("UDP数据包已发送:" + msg);
        } catch (Exception e) {
            e.printStackTrace();
        }
    }
}

接收端代码(Receiver)

import java.net.DatagramPacket;
import java.net.DatagramSocket;

public class UdpReceiver {
    public static void main(String[] args) {
        // 监听的端口号
        int port = 9999;
        try (
            // 创建UDP套接字,绑定指定端口
            DatagramSocket socket = new DatagramSocket(port);
        ) {
            // 1. 创建缓冲区,用于接收数据(长度建议设为1024或更大)
            byte[] buffer = new byte[1024];
            DatagramPacket packet = new DatagramPacket(buffer, buffer.length);
            System.out.println("UDP接收端已启动,等待数据...");
            // 2. 接收数据包(阻塞方法,直到收到数据)
            socket.receive(packet);
            // 3. 解析数据包(注意截取有效数据,避免空字符)
            String msg = new String(packet.getData(), 0, packet.getLength());
            System.out.println("收到来自 " + packet.getAddress() + " 的消息:" + msg);
        } catch (Exception e) {
            e.printStackTrace();
        }
    }
}

运行步骤:先启动UdpReceiver,再启动UdpSender,接收端会打印发送端的 IP 和消息。

四、避坑指南:3 个常见问题及解决方案​

  1. 问题 1:Socket 关闭顺序错误导致资源泄漏​

解决方案:先关输出流,再关输入流,最后关 Socket;或用 try-with-resources(本文 demo 已用,自动关闭资源)。​

  1. 问题 2:TCP 粘包 / 拆包(多次发送的消息被合并接收)​

解决方案:定义消息格式(如 “消息长度 + 消息内容”),接收端先读长度,再按长度读内容;或用分隔符(如\n)分割消息。​

  1. 问题 3:UDP 数据包丢失​

解决方案:关键场景可添加 “确认机制”(如接收端收到后回复 ACK);或限制数据包大小(建议不超过 1472 字节,避免分片)。​

五、总结与后续学习方向​

本文覆盖了 Java 网络编程的核心:Socket 基础、TCP/UDP 实战、IO 模型对比和避坑技巧,新手通过本文的 demo 能快速建立认知,上手实践。​

如果想进一步提升,推荐后续学习:​

  1. Netty 框架(简化 NIO 开发,企业级常用)​
  1. HTTP 协议编程(用java.net.HttpURLConnection或 OkHttp 库)​
  1. 网络安全(SSL/TLS 加密,SSLSocket类)​

如果本文对你有帮助,欢迎点赞收藏,评论区留言讨论你的实践遇到的问题~​

Logo

有“AI”的1024 = 2048,欢迎大家加入2048 AI社区

更多推荐