Java 实现轻量型 HTTP 代理服务器示例
如何利用原生 Java 快速搭建一个简单的 HTTP 代理服务?本方案通过 java.net 包中的套接字(Socket)技术,实现了连接监听、HTTP 头解析及数据流中转功能,无需任何第三方库即可运行。
结果与目标
我们的目标是构建一个极简的 HTTP 代理,它具备以下能力: 1. 在指定端口监听传入的 HTTP 请求。 2. 解析请求头以获取目标地址(Host Header)。 3. 建立与目标服务器的新连接,并双向转发客户端与服务端之间的数据。 4. 使用独立线程处理每个会话,以支持并发访问。
准备条件
- 开发环境:安装 JDK 8 或更高版本。
- 核心类依赖:
java.io用于 I/O 操作,java.net用于网络连接,java.util.concurrent(隐含在线程中)用于并发控制。 - 编译工具:命令行 javac 或任何 IDE(如 IntelliJ IDEA, Eclipse)。
真实操作顺序
第1步:设置主服务监听入口
目的:创建一个后台守护线程,持续监听特定端口等待客户端连接。
入口:HttpProxy 类的构造方法与静态内部类 HTTPSession。
动作:
1. 实例化 ServerSocket 并绑定到配置端口(默认 8580)。
myServerSocket = new ServerSocket(myTcpPort);
2. 启动一个守护线程,循环调用 myServerSocket.accept() 阻塞等待连接。
new Thread(new Runnable() {
public void run() {
try {
while (true)
new HTTPSession(myServerSocket.accept());
} catch (IOException ioe) { /* 忽略 */ }
}
}).start();
3. 将主线程设置为 Daemon 模式,确保服务随 JVM 退出而终止。
第2步:解析 HTTP 请求头部
目的:从原始字节流中识别出 HTTP 协议头部的结束位置,并提取目标主机地址。
入口:findHeaderEnd 方法。
动作:
1. 读取客户端输入流的数据到缓冲区(Buffer)。由于 TCP 是流式传输,HTTP 头部可能跨越多个数据包,需循环读取直到找到尾部标记。
// 读取数据并寻找 \r\n\r\n 标记
while (read > 0) {
rlen += read;
splitbyte = findHeaderEnd(buf, rlen);
if (splitbyte > 0) break;
read = is.read(buf, rlen, bufsize - rlen);
}
2. 使用 BufferedReader 解析文本头部,查找 Host: 字段。
if (string.toLowerCase().startsWith("host:")) {
host.host = string;
// ... 处理标志位
}
第3步:计算目标服务器地址
目的:从 Host 头部字符串中拆解 IP/域名和端口号。
入口:Host.cal() 方法。
动作:
1. 定位冒号位置以确定分隔符。若存在冒号,则截取前部分为地址,后部分转为整数作为端口;若不存在,默认端口设为 80。
if (next == -1) {
port = 80;
address = host.substring(start + 2);
} else {
address = host.substring(start + 2, next);
port = Integer.valueOf(host.substring(next + 1));
}
第4步:建立代理连接并双向管道传输
目的:将客户端的请求转发给真正的目标服务器,并将响应回传给客户端。
入口:pipe() 方法。
动作:
1. 实例化指向目标地址的新 Socket,并设置超时时间(setSoTimeout(3000))以防止长期挂起。
Socket socket = new Socket(host.address, host.port);
socket.setSoTimeout(3000);
2. 将解析出的头部写入目标连接。
os.write(request, 0, requestLen);
3. 进入轮询循环:读取目标服务器的响应并立即写回客户端,同时检查是否有新的客户端请求需要继续转发。一旦任一端关闭或发生异常,则清理资源。
第5步:启动服务
目的:在本地环境中启动代理程序。
入口:main() 方法。
动作:
1. 创建 HttpProxy 实例并指定监听端口。
new HttpProxy(8580);
2. 主线程通过 System.in.read() 保持存活,按回车键可触发 stop() 方法关闭服务端。
完成判断
当控制台输出 start! 且没有报错时,代理已在 8580 端口就绪。您可以通过浏览器或 curl 工具,将代理服务器设置为本机 IP 和端口 8580,此时请求将被正确转发。注意:此示例主要演示 HTTP 透明代理的基础逻辑,生产环境建议使用 Apache HttpClient、Netty 等成熟框架以应对复杂的头部处理和 SSL/TLS 终端问题。
简要总结
以上就是利用 Java 原生 Socket 实现轻量型 HTTP 代理服务器的详细内容,更多关于 Java 网络编程及本地部署的资料请关注本站其它相关文章!
免责声明:本文内容仅供参考,不代表本站观点。转载或引用请注明出处。









