network-programming

Java 网络编程

Java Maven License

一个完整的 Java 网络编程学习项目,涵盖 BIO、NIO、AIO 三种 I/O 模型,以及 NIO Buffer 和回调模式示例

📋 目录

项目简介

本项目通过实际的代码示例,演示 Java 中三种不同的 I/O 编程模型:

I/O 模型 特点 适用场景
BIO 阻塞式,一个连接一个线程 连接数较少且固定的场景
NIO 非阻塞,多路复用 连接数多但连接时间短的场景
AIO 异步非阻塞 连接数多且连接时间长的场景

技术栈

项目结构

network-programming/
├── pom.xml                           # Maven 配置文件
├── README.md                         # 项目说明文档
├── LICENSE                           # 许可证文件
└── src/
    └── main/
        ├── java/                     # Java 源代码
        │   ├── aio/                  # 异步 I/O (AIO)
        │   │   ├── Client.java
        │   │   └── Server.java
        │   ├── bio/                  # 阻塞 I/O (BIO)
        │   │   ├── tcp/              # TCP 通信
        │   │   │   ├── Client.java
        │   │   │   ├── MultiThreadServer.java
        │   │   │   └── SingleThreadServer.java
        │   │   └── udp/              # UDP 通信
        │   │       ├── Client.java
        │   │       └── Server.java
        │   ├── callback/             # 回调模式示例
        │   │   ├── AsyncCalculator.java
        │   │   ├── Client.java
        │   │   └── ResultCallback.java
        │   ├── nio/                  # 非阻塞 I/O (NIO)
        │   │   ├── buffer/           # Buffer 示例
        │   │   │   ├── DirectBuffer.java
        │   │   │   ├── HeapBuffer.java
        │   │   │   ├── MappedBuffer.java
        │   │   │   ├── ReadOnlyBuffer.java
        │   │   │   └── SubBuffer.java
        │   │   ├── other/            # 文件、管道等其他 NIO 示例
        │   │   │   ├── NioAsynchronousFileChannel.java
        │   │   │   ├── NioFileLock.java
        │   │   │   └── NioPipe.java
        │   │   ├── tcp/              # TCP 聊天室
        │   │   │   ├── Client.java
        │   │   │   └── Server.java
        │   │   └── udp/              # UDP 通信
        │   │       ├── Client.java
        │   │       └── Server.java
        │   └── util/                 # 工具类
        │       ├── NetworkConfig.java
        │       ├── TCPUtil.java
        │       └── UDPUtil.java
        └── resources/                # 资源文件
            ├── image/                # 图片资源
            │   ├── 堆内缓冲区.jpeg
            │   └── 直接缓冲区.jpeg
            ├── txt/
            │   ├── async-file-channel.txt
            │   ├── file-lock.txt
            │   └── mapped-buffer.txt
            └── logback.xml           # 日志配置文件

模块说明

BIO (Blocking I/O)

传统的阻塞式 I/O 模型,每个连接都需要一个独立的线程处理

特点

运行方式

# 1. 启动服务端(选择一个)
mvn exec:java -Dexec.mainClass="bio.tcp.SingleThreadServer"
mvn exec:java -Dexec.mainClass="bio.tcp.MultiThreadServer"

# 2. 启动客户端
mvn exec:java -Dexec.mainClass="bio.tcp.Client"

NIO (Non-blocking I/O)

基于 Channel、Buffer、Selector 的非阻塞 I/O 模型

特点

聊天室示例

# 1. 启动服务端
mvn exec:java -Dexec.mainClass="nio.tcp.Server"

# 2. 启动多个客户端(分别在不同终端执行同一个客户端类)
mvn exec:java -Dexec.mainClass="nio.tcp.Client"
mvn exec:java -Dexec.mainClass="nio.tcp.Client"

断连行为

UDP 通信示例

# 1. 启动服务端
mvn exec:java -Dexec.mainClass="nio.udp.Server"

# 2. 启动客户端
mvn exec:java -Dexec.mainClass="nio.udp.Client"

核心组件: | 组件 | 说明 | |:—:|:—:| | Selector | 多路复用器,用于轮询 Channel 上的事件 | | Channel | 双向通道,可读可写 | | Buffer | 数据容器,读写数据的中转站 | | DatagramChannel | UDP 数据报通道 |

NIO Buffer 示例

这一组示例聚焦 ByteBuffer 的典型用法和常见陷阱,适合和网络 I/O 一起学习。

类名 演示重点
nio.buffer.HeapBuffer 展示堆内缓冲区的写入、flip() 切换到读模式后的状态变化
nio.buffer.DirectBuffer 展示直接缓冲区的创建和顺序读取
nio.buffer.ReadOnlyBuffer 展示只读缓冲区与原始缓冲区共享数据,但自身不可写
nio.buffer.SubBuffer 展示 slice() 创建子缓冲区后,底层数据共享带来的联动效果
nio.buffer.MappedBuffer 展示 MappedByteBuffer 将文件映射到内存后直接读取内容

适合关注的点

NIO 其他示例

这一组示例补充了文件通道、文件锁和管道这几个常见主题,适合和 ByteBufferChannel 一起理解。

类名 演示重点
nio.other.NioAsynchronousFileChannel 展示 AsynchronousFileChannel 的异步读取、异步写入和 CompletionHandler 回调
nio.other.NioFileLock 展示排它锁和共享锁的基本流程,说明文件锁主要用于进程间协作
nio.other.NioPipe 展示 Pipe 在两个线程之间进行单向数据传输

适合关注的点

AIO (Asynchronous I/O)

JDK 7 引入的异步 I/O,基于回调机制

特点

运行方式

# 1. 启动服务端
mvn exec:java -Dexec.mainClass="aio.Server"

# 2. 启动客户端
mvn exec:java -Dexec.mainClass="aio.Client"

核心组件: | 组件 | 说明 | |:—:|:—:| | AsynchronousServerSocketChannel | 异步服务端 Socket 通道 | | AsynchronousSocketChannel | 异步客户端 Socket 通道 | | CompletionHandler | 异步操作完成后的回调处理器 |

回调模式示例

演示异步编程中的回调模式,实现计算与结果处理的解耦。

文件说明

文件 说明
AsyncCalculator.java 异步计算器,执行耗时计算并通过回调返回结果
ResultCallback.java 回调接口,定义计算完成后的处理逻辑
Client.java 使用示例,演示如何使用回调模式
public class Client {
    static void main(String[] args) {
        AsyncCalculator calculator = new AsyncCalculator();
        calculator.run(1, 2, result -> System.out.println("计算结果: " + result));
    }
}

快速开始

环境要求

编译项目

mvn clean compile

运行测试

mvn test

运行示例

TCP 通信示例

# 终端 1 - 启动服务端
mvn exec:java -Dexec.mainClass="bio.tcp.SingleThreadServer"

# 终端 2 - 启动客户端
mvn exec:java -Dexec.mainClass="bio.tcp.Client"

UDP 通信示例

# 终端 1 - 启动服务端
mvn exec:java -Dexec.mainClass="bio.udp.Server"

# 终端 2 - 启动客户端
mvn exec:java -Dexec.mainClass="bio.udp.Client"

NIO 聊天室示例

# 终端 1 - 启动聊天室服务端
mvn exec:java -Dexec.mainClass="nio.tcp.Server"

# 终端 2 - 启动客户端 1
mvn exec:java -Dexec.mainClass="nio.tcp.Client"

# 终端 3 - 启动客户端 2
mvn exec:java -Dexec.mainClass="nio.tcp.Client"

运行后按提示输入昵称即可;如果你在 IDEA 中运行,记得给 nio.tcp.Client 的运行配置开启“允许多个实例”。

NIO Buffer 示例

# 堆内缓冲区:观察 position / limit / capacity 的变化
mvn exec:java -Dexec.mainClass="nio.buffer.HeapBuffer"

# 直接缓冲区:演示 allocateDirect 创建的缓冲区读取流程
mvn exec:java -Dexec.mainClass="nio.buffer.DirectBuffer"

# 只读缓冲区:演示共享数据与只读限制
mvn exec:java -Dexec.mainClass="nio.buffer.ReadOnlyBuffer"

# 子缓冲区:演示 slice() 后的共享底层数组
mvn exec:java -Dexec.mainClass="nio.buffer.SubBuffer"

# 内存映射缓冲区:读取 src/main/resources/txt/mapped-buffer.txt
mvn exec:java -Dexec.mainClass="nio.buffer.MappedBuffer"

NIO 文件与管道示例

# 异步文件通道:读取并写入 src/main/resources/txt/async-file-channel.txt
mvn exec:java -Dexec.mainClass="nio.other.NioAsynchronousFileChannel"

# 文件锁:演示排它锁和共享锁访问 src/main/resources/txt/file-lock.txt
mvn exec:java -Dexec.mainClass="nio.other.NioFileLock"

# 管道:演示两个线程之间的单向数据传输
mvn exec:java -Dexec.mainClass="nio.other.NioPipe"

图示说明

堆内缓冲区 (Heap Buffer)

数据存储在 JVM 堆内存中,创建和销毁速度快,但数据复制到 Native 内存时会有性能开销

直接缓冲区 (Direct Buffer)

数据存储在 Native 内存中,避免了数据拷贝,适合频繁的 I/O 操作,但创建和销毁成本较高

核心概念对比

特性 BIO NIO AIO
线程模型 1:1 (连接:线程) 1:N (Selector:连接) 回调驱动
阻塞性 阻塞 非阻塞 异步非阻塞
API 复杂度 简单 中等 中等
吞吐量
延迟
JDK 版本 1.0+ 1.4+ 1.7+

配置说明

网络配置位于 src/main/java/util/NetworkConfig.java

public class NetworkConfig {
    public static final String HOST = "127.0.0.1";    // 服务端地址
    public static final int PORT = 9000;               // 服务端端口
    public static final int BUFFER_SIZE = 1024;        // 缓冲区大小
}

以下示例依赖 src/main/resources/txt 目录下的文本文件,运行时请从项目根目录启动命令:

❓ 常见问题 (FAQ)

1. BIO、NIO、AIO 有什么区别?

对比项 BIO NIO AIO
阻塞方式 阻塞 非阻塞 异步非阻塞
线程模型 一连接一线程 一线程处理多连接 回调驱动
适用场景 连接数少且固定 连接数多但时间短 连接数多且时间长

2. TCP 和 UDP 如何选择?

协议 特点 适用场景
TCP 可靠传输、有序、有连接 文件传输、邮件、网页浏览
UDP 不可靠、无连接、速度快 视频直播、DNS、游戏

3. 运行时提示端口被占用怎么办?

修改 NetworkConfig.java 中的 PORT 值,或终止占用端口的进程:

# Windows 查看端口占用
netstat -ano | findstr :9000

# 终止进程 (PID 为上一步查到的进程ID)
taskkill /PID <进程ID> /F

4. 为什么 NIO 示例中客户端连接后没有反应?

确保先启动服务端,再启动客户端。NIO 是非阻塞的,客户端连接需要服务端先监听。

5. 堆内缓冲区和直接缓冲区如何选择?

类型 优点 缺点 适用场景
Heap Buffer 创建快、GC 管理 I/O 需要复制 短生命周期、数据量小
Direct Buffer 零拷贝、I/O 高效 创建慢、需手动释放 长生命周期、频繁 I/O

6. 为什么 Buffer 示例里反复强调 flip()

因为 ByteBuffer 写入数据后,position 已经移动到末尾;如果不先 flip(),读取时 limit 仍然是容量上限,容易读不到预期内容。 nio.buffer.HeapBuffer 就是专门用来观察这个状态切换的。

📚 学习资源推荐

官方文档

推荐书籍

相关项目

贡献

欢迎提交 Issue 和 Pull Request

许可证

本项目采用 MIT License 开源许可证