Java 8 或以上
(可选)Python/Shell/.bat 支持以执行 CGI
1.客户端代码TcpClient.java
2.服务器代码TcpServer.java
3.实现的业务逻辑:
客户端:启动多个线程,每个线程模拟一个并发请求。每个线程在给定时间内(TEST_TIME)反复请求文件列表中的文件,并计算等待时间和吞吐量等统计数据。每个线程会计算吞吐量、数据传输速率和平均等待时间,并打印结果
服务端:等待并接受客户端连接。为每个客户端连接创建一个独立的线程,来处理客户端的请求。接收客户端发送的消息,并返回响应。关闭客户端连接,并处理异常。
├── .idea // IntelliJ IDEA 配置文件
├── out // 编译输出文件
├── TCP and File stream try // 主要项目文件夹
│ ├── .idea // 项目的 IntelliJ 配置文件
│ ├── .gitignore // Git 忽略文件配置
│ ├── files.txt // 文件列表或其他数据文件
│ ├── TCP and File stream try.iml // IntelliJ 项目文件
│ ├── 1a.iml // 项目配置文件
│ ├── TCP and File stream.iml // 项目配置文件
├── src // 源代码目录
│ ├── Main // 主类目录,包含程序的入口
│ ├── TcpClient // 客户端类目录,包含与服务器通信的客户端实现
│ ├── TcpServer // 服务器类目录,包含处理客户端请求的服务器实现
├── httpd.conf # 服务器配置文件
├── manifest.mf (可选) # JAR 打包入口声明
├── src/minihttpd/ # Java 源码
│ ├── Main.java # 简化入口(仅线程模式)
│ ├── Server.java # 全功能入口(支持 -config 与 -thread)
│ ├── ServerConfig.java # 解析 httpd.conf
│ ├── WebServer.java # 接收连接与调度线程
│ ├── WebServerHandler.java# 请求处理逻辑,含日志输出
│ ├── CacheManager.java # LRU 缓存管理
│ ├── VirtualHost.java # 虚拟主机模型
│ ├── Monitor.java # 监控接口
│ └── SimpleMonitor.java # 默认心跳监测
├── wwwroot/ # 默认文档根目录
│ ├── index.html
│ ├── 404.html
│ ├── css/main.css
│ └── js/app.js
└── out/production/change1/ # 编译输出 & 示例 CGI 脚本
Listen 6789
CacheSize 1024
<VirtualHost *:6789>
ServerName localhost # Host 头匹配
DocumentRoot wwwroot # 静态文件与 CGI 根目录
Monitor minihttpd.YourMonitorImpl
Listen 与 中的端口必须一致
ServerName 应与浏览器访问的主机名或 IP 对应
- 使用 Server 全功能入口
# 切到项目根目录(httpd.conf 所在目录)
cd /d D:...\1b
# 单线程(顺序)模式
java -cp out\production\change1 minihttpd.Server -config httpd.conf
# 多线程(线程池并发)模式
java -cp out\production\change1 minihttpd.Server -config httpd.conf -thread
IDEA 配置(Run → Edit Configurations)
Main class:minihttpd.Server
Working directory:项目根目录(含 httpd.conf)
Program arguments:
顺序:-config httpd.conf
并发:-config httpd.conf -thread
- 使用 Main 简化入口
// Main.java 中永远线程模式
String conf = args.length>0 ? args[0] : "httpd.conf";
new WebServer(cfg, true).start();
# 项目根目录下运行:
java -cp out\production\change1 minihttpd.Main httpd.conf
# 或者:
java -cp out\production\change1 minihttpd.Main
在 WebServerHandler 中打印:
// 每个请求开始/结束时输出
System.out.printf("[%s] [%s] START %s%n", time, threadName, uri);
System.out.printf("[%s] [%s] FINISH %s%n", time, threadName, uri);
单线程模式:日志线程名均为 [main],请求依次执行
多线程模式:日志线程名为 [pool-1-thread-x] 或自定义名,请求并发处理
通过同时发起 /slow(内部 sleep(5000))与 /index.html,对比两种模式日志,即可直观看出差异。
wwwroot/hello.cgi:
#!/usr/bin/env python
print('Content-Type: text/plain\n')
print('Hello CGI!')
浏览器访问:
http://localhost:6789/hello.cgi
│ │ ├── ConfigReader.java # 配置读取类
│ │ ├── Main.java # 主程序入口
│ │ ├── ThreadPoolAcceptServer.java # 线程池接收服务器
│ │ ├── ThreadPoolWaitNotifyServer.java # 线程池等待通知服务器
│ │ └── WorkerThread.java # 工作线程类
│ ├── .gitignore # Git 忽略文件配置
│ ├── 2a.iml # IntelliJ IDEA 模块配置文件
├── BusyWaitThreadPool # 忙等待线程池实现
├── Config # 配置参数定义
├── ConfigReader # 配置文件读取与解析
├── HttpHandler # HTTP协议请求处理
├── Main # 主程序入口
├── TestClient # 高级/扩展测试客户端
├── Thread_server # 服务线程(竞争accept)
├── ThreadPool # 线程池核心实现
├── ThreadPoolAcceptServer # 使用线程池+accept的服务器实现
│ ├── HardcodedBench # Java 主类(无 .java 后缀,应为源码文件 HardcodedBench.java)测试文件
│ └── hello.cgi # CGI 脚本文件
每次测试仅需要改变端口号就行