本文目录导读:

我将为您提供几个Java代理服务器的完整案例,从简单到复杂,涵盖不同实现方式。
简单HTTP转发代理
这是一个基础的HTTP代理服务器,能够转发HTTP请求和响应:
import java.io.*;
import java.net.*;
public class SimpleHttpProxy {
private static final int PORT = 8080;
private static final int BUFFER_SIZE = 8192;
public static void main(String[] args) {
System.out.println("简单HTTP代理服务器启动,监听端口: " + PORT);
try (ServerSocket serverSocket = new ServerSocket(PORT)) {
while (true) {
Socket clientSocket = serverSocket.accept();
System.out.println("客户端连接: " + clientSocket.getInetAddress());
new Thread(() -> handleClient(clientSocket)).start();
}
} catch (IOException e) {
e.printStackTrace();
}
}
private static void handleClient(Socket clientSocket) {
try (clientSocket;
InputStream clientIn = clientSocket.getInputStream();
OutputStream clientOut = clientSocket.getOutputStream()) {
// 读取客户端请求
byte[] requestBytes = readRequest(clientIn);
String request = new String(requestBytes);
if (request.isEmpty()) {
return;
}
System.out.println("收到请求: " + request.split("\n")[0]);
// 解析请求行,获取URL
String[] lines = request.split("\r\n");
String requestLine = lines[0];
String[] parts = requestLine.split(" ");
if (parts.length < 3) {
sendErrorResponse(clientOut, 400, "Bad Request");
return;
}
String url = parts[1];
System.out.println("请求URL: " + url);
// 转发请求到目标服务器
forwardRequest(clientOut, requestBytes, url);
} catch (Exception e) {
e.printStackTrace();
}
}
private static byte[] readRequest(InputStream in) throws IOException {
ByteArrayOutputStream buffer = new ByteArrayOutputStream();
byte[] temp = new byte[BUFFER_SIZE];
int read;
// 简单方式:读取直到连接关闭或者超时
try {
in.setSoTimeout(1000);
while ((read = in.read(temp)) != -1) {
buffer.write(temp, 0, read);
if (buffer.size() > BUFFER_SIZE * 100) break; // 防止过大请求
}
} catch (SocketTimeoutException e) {
// 超时说明请求读取完毕
}
return buffer.toByteArray();
}
private static void forwardRequest(OutputStream clientOut, byte[] requestBytes, String url)
throws IOException {
// 解析URL
URL targetUrl = new URL(url);
int port = targetUrl.getPort() == -1 ? 80 : targetUrl.getPort();
String host = targetUrl.getHost();
// 建立到目标服务器的连接
try (Socket targetSocket = new Socket(host, port);
OutputStream targetOut = targetSocket.getOutputStream();
InputStream targetIn = targetSocket.getInputStream()) {
// 发送请求到目标服务器
targetOut.write(requestBytes);
targetOut.flush();
// 接收响应并转发给客户端
byte[] buffer = new byte[BUFFER_SIZE];
int read;
while ((read = targetIn.read(buffer)) != -1) {
clientOut.write(buffer, 0, read);
clientOut.flush();
}
}
}
private static void sendErrorResponse(OutputStream out, int code, String message)
throws IOException {
String response = "HTTP/1.1 " + code + " " + message + "\r\n" +
"Content-Type: text/plain\r\n" +
"Content-Length: " + message.length() + "\r\n" +
"Connection: close\r\n\r\n" +
message;
out.write(response.getBytes());
out.flush();
}
}
HTTPS CONNECT代理
支持HTTPS的CONNECT方法代理:
import java.io.*;
import java.net.*;
public class ConnectProxy {
private static final int PORT = 8080;
private static final int BUFFER_SIZE = 8192;
public static void main(String[] args) {
System.out.println("HTTPS CONNECT代理服务器启动,监听端口: " + PORT);
try (ServerSocket serverSocket = new ServerSocket(PORT)) {
while (true) {
Socket clientSocket = serverSocket.accept();
new Thread(() -> handleClient(clientSocket)).start();
}
} catch (IOException e) {
e.printStackTrace();
}
}
private static void handleClient(Socket clientSocket) {
try {
BufferedReader reader = new BufferedReader(
new InputStreamReader(clientSocket.getInputStream()));
// 读取请求头
String requestLine = reader.readLine();
System.out.println("请求行: " + requestLine);
if (requestLine == null) return;
String[] parts = requestLine.split(" ");
String method = parts[0];
if (!method.equals("CONNECT")) {
// 非CONNECT请求,返回405
sendResponse(clientSocket.getOutputStream(), 405,
"HTTP/1.1 405 Method Not Allowed\r\n\r\n");
return;
}
// 解析host:port
String[] hostPort = parts[1].split(":");
String host = hostPort[0];
int port = Integer.parseInt(hostPort[1]);
// 读取请求头
String line;
while (!(line = reader.readLine()).isEmpty()) {
System.out.println("请求头: " + line);
}
// 尝试连接目标服务器
try {
Socket targetSocket = new Socket(host, port);
System.out.println("连接目标服务器成功: " + host + ":" + port);
// 发送200响应
sendResponse(clientSocket.getOutputStream(), 200,
"HTTP/1.1 200 Connection Established\r\n\r\n");
// 建立双向隧道
Thread t1 = new Thread(() -> tunnel(clientSocket, targetSocket));
Thread t2 = new Thread(() -> tunnel(targetSocket, clientSocket));
t1.start();
t2.start();
// 等两个线程结束
t1.join();
t2.join();
} catch (IOException e) {
System.out.println("无法连接到目标服务器: " + host + ":" + port);
sendResponse(clientSocket.getOutputStream(), 502,
"HTTP/1.1 502 Bad Gateway\r\n\r\n");
}
} catch (Exception e) {
e.printStackTrace();
}
}
private static void tunnel(Socket from, Socket to) {
try (InputStream in = from.getInputStream();
OutputStream out = to.getOutputStream()) {
byte[] buffer = new byte[BUFFER_SIZE];
int read;
while ((read = in.read(buffer)) != -1) {
out.write(buffer, 0, read);
out.flush();
System.out.println("转发 " + read + " 字节");
}
} catch (IOException e) {
// 连接断开
}
}
private static void sendResponse(OutputStream out, int code, String response)
throws IOException {
out.write(response.getBytes());
out.flush();
}
}
轻量级高性能代理(基于NIO)
使用Java NIO实现的非阻塞代理服务器:
import java.io.IOException;
import java.net.InetSocketAddress;
import java.nio.ByteBuffer;
import java.nio.channels.*;
import java.util.*;
import java.util.concurrent.*;
public class NioProxyServer {
private static final int PORT = 8080;
private static final int BUFFER_SIZE = 65536;
// 用于记录管道连接
private static class Tunnel {
SocketChannel clientChannel;
SocketChannel targetChannel;
boolean clientClosed = false;
boolean targetClosed = false;
// 关闭连接
public synchronized void closeAll() {
try {
if (targetChannel != null) {
targetChannel.close();
}
if (clientChannel != null) {
clientChannel.close();
}
} catch (IOException e) {
e.printStackTrace();
}
}
}
public static void main(String[] args) throws IOException {
Selector selector = Selector.open();
ServerSocketChannel serverChannel = ServerSocketChannel.open();
serverChannel.configureBlocking(false);
serverChannel.bind(new InetSocketAddress(PORT));
serverChannel.register(selector, SelectionKey.OP_ACCEPT);
System.out.println("NIO代理服务器启动,监听端口: " + PORT);
while (true) {
// 等待事件
selector.select(1000);
Iterator<SelectionKey> keys = selector.selectedKeys().iterator();
while (keys.hasNext()) {
SelectionKey key = keys.next();
keys.remove();
if (!key.isValid()) {
continue;
}
if (key.isAcceptable()) {
// 接受新的客户端连接
acceptClient(selector, serverChannel);
} else if (key.isConnectable()) {
// 连接目标服务器完成
handleConnect(key);
} else if (key.isReadable()) {
// 有数据可读
handleRead(key, selector);
}
}
}
}
private static void acceptClient(Selector selector, ServerSocketChannel serverChannel)
throws IOException {
SocketChannel clientChannel = serverChannel.accept();
clientChannel.configureBlocking(false);
System.out.println("新客户端连接: " + clientChannel.getRemoteAddress());
// 注册读取事件处理CONNECT请求
clientChannel.register(selector, SelectionKey.OP_READ);
}
private static void handleConnect(SelectionKey key) {
Tunnel tunnel = (Tunnel) key.attachment();
SocketChannel targetChannel = (SocketChannel) key.channel();
try {
if (targetChannel.finishConnect()) {
System.out.println("目标服务器连接成功");
// 发送200响应给客户端
String response = "HTTP/1.1 200 Connection Established\r\n\r\n";
ByteBuffer buffer = ByteBuffer.wrap(response.getBytes());
tunnel.clientChannel.write(buffer);
// 注册双方读取事件
tunnel.clientChannel.register(key.selector(), SelectionKey.OP_READ, tunnel);
targetChannel.register(key.selector(), SelectionKey.OP_READ, tunnel);
System.out.println("隧道建立成功");
}
} catch (IOException e) {
e.printStackTrace();
tunnel.closeAll();
key.cancel();
}
}
private static void handleRead(SelectionKey key, Selector selector) {
Tunnel tunnel = (Tunnel) key.attachment();
SocketChannel readChannel = (SocketChannel) key.channel();
try {
ByteBuffer buffer = ByteBuffer.allocate(BUFFER_SIZE);
int bytesRead = readChannel.read(buffer);
if (bytesRead == -1) {
// 连接已关闭
System.out.println("连接关闭");
tunnel.closeAll();
key.cancel();
return;
}
if (bytesRead > 0) {
buffer.flip();
// 确定是哪个方向的通道
SocketChannel writeChannel = null;
if (readChannel == tunnel.clientChannel) {
writeChannel = tunnel.targetChannel;
} else {
writeChannel = tunnel.clientChannel;
}
// 转发数据
writeChannel.write(buffer);
System.out.println("转发 " + bytesRead + " 字节");
}
} catch (IOException e) {
e.printStackTrace();
tunnel.closeAll();
key.cancel();
}
}
}
带有缓存功能的代理服务器
import java.io.*;
import java.net.*;
import java.util.concurrent.ConcurrentHashMap;
import java.nio.file.*;
public class HttpCacheProxy {
private static final int PORT = 8080;
private static final ConcurrentHashMap<String, CacheEntry> cache = new ConcurrentHashMap<>();
private static final long CACHE_DURATION = 5 * 60 * 1000; // 5分钟
static class CacheEntry {
byte[] data;
long timestamp;
CacheEntry(byte[] data, long timestamp) {
this.data = data;
this.timestamp = timestamp;
}
boolean isExpired() {
return System.currentTimeMillis() - timestamp > CACHE_DURATION;
}
}
public static void main(String[] args) {
System.out.println("缓存代理服务器启动,监听端口: " + PORT);
try (ServerSocket serverSocket = new ServerSocket(PORT)) {
while (true) {
Socket clientSocket = serverSocket.accept();
new Thread(() -> handleClient(clientSocket)).start();
}
} catch (IOException e) {
e.printStackTrace();
}
}
private static void handleClient(Socket clientSocket) {
try (clientSocket;
InputStream in = clientSocket.getInputStream();
OutputStream out = clientSocket.getOutputStream()) {
// 读取请求
byte[] requestData = readRequest(in);
String request = new String(requestData);
// 解析请求
String[] lines = request.split("\r\n");
String[] parts = lines[0].split(" ");
String method = parts[0];
String url = parts[1];
// 只处理GET请求的缓存
if (method.equals("GET")) {
// 检查缓存
if (cache.containsKey(url)) {
CacheEntry entry = cache.get(url);
if (!entry.isExpired()) {
System.out.println("命中缓存: " + url + " 缓存大小: " + entry.data.length);
out.write(entry.data);
return;
} else {
cache.remove(url);
}
}
// 转发请求并从目标服务器获取响应
byte[] response = forwardGetRequest(url);
if (response != null && !requestContainsNoCache(lines)) {
// 缓存响应
cache.put(url, new CacheEntry(response, System.currentTimeMillis()));
System.out.println("缓存响应: " + url + " 大小: " + response.length);
}
out.write(response);
} else {
// 非GET请求直接转发
forwardRequestDirectly(out, requestData, url);
}
} catch (Exception e) {
e.printStackTrace();
}
}
private static byte[] readRequest(InputStream in) throws IOException {
ByteArrayOutputStream buffer = new ByteArrayOutputStream();
byte[] temp = new byte[4096];
int read;
try {
in.setSoTimeout(2000);
while ((read = in.read(temp)) != -1) {
buffer.write(temp, 0, read);
if (buffer.size() > 100000) break; // 限制请求大小
}
} catch (SocketTimeoutException e) {
// 请求读取完成
}
return buffer.toByteArray();
}
private static byte[] forwardGetRequest(String url) throws IOException {
URL targetUrl = new URL(url);
HttpURLConnection conn = (HttpURLConnection) targetUrl.openConnection();
conn.setRequestMethod("GET");
conn.setConnectTimeout(5000);
conn.setReadTimeout(5000);
int responseCode = conn.getResponseCode();
System.out.println("目标服务器响应: " + responseCode);
if (responseCode >= 200 && responseCode < 300) {
try (InputStream in = conn.getInputStream();
ByteArrayOutputStream buffer = new ByteArrayOutputStream()) {
byte[] temp = new byte[4096];
int read;
while ((read = in.read(temp)) != -1) {
buffer.write(temp, 0, read);
}
// 构建完整的HTTP响应
String headers = "HTTP/1.1 " + responseCode + " " +
conn.getResponseMessage() + "\r\n";
Map<String, List<String>> headerFields = conn.getHeaderFields();
for (Map.Entry<String, List<String>> entry : headerFields.entrySet()) {
if (entry.getKey() != null) {
for (String value : entry.getValue()) {
headers += entry.getKey() + ": " + value + "\r\n";
}
}
}
headers += "\r\n";
byte[] headerBytes = headers.getBytes();
byte[] response = new byte[headerBytes.length + buffer.size()];
System.arraycopy(headerBytes, 0, response, 0, headerBytes.length);
System.arraycopy(buffer.toByteArray(), 0, response, headerBytes.length, buffer.size());
return response;
}
}
return ("HTTP/1.1 " + responseCode + " " +
conn.getResponseMessage() + "\r\n\r\n").getBytes();
}
private static void forwardRequestDirectly(OutputStream clientOut, byte[] requestData,
String url) throws IOException {
URL targetUrl = new URL(url);
int port = targetUrl.getPort() == -1 ? 80 : targetUrl.getPort();
try (Socket targetSocket = new Socket(targetUrl.getHost(), port);
OutputStream targetOut = targetSocket.getOutputStream();
InputStream targetIn = targetSocket.getInputStream()) {
targetOut.write(requestData);
targetOut.flush();
byte[] buffer = new byte[4096];
int read;
while ((read = targetIn.read(buffer)) != -1) {
clientOut.write(buffer, 0, read);
clientOut.flush();
}
}
}
private static boolean requestContainsNoCache(String[] headers) {
for (String header : headers) {
if (header.toLowerCase().contains("no-cache") ||
header.toLowerCase().contains("no-store") ||
header.toLowerCase().contains("max-age=0")) {
return true;
}
}
return false;
}
}
代理服务器配置文件
proxy-config.properties:
# 代理服务器配置 proxy.port=8080 proxy.maxThreads=100 proxy.connectTimeout=5000 proxy.readTimeout=5000 # 缓存配置 cache.enabled=true cache.duration=300000 cache.maxSize=100MB # 日志配置 log.enabled=true log.file=proxy.log
使用说明
运行方式:
# 编译 javac SimpleHttpProxy.java # 运行 java SimpleHttpProxy
测试方法:
# 配置浏览器使用代理 # HTTP Proxy: 127.0.0.1 # Port: 8080 # 或者使用curl测试 curl -x http://127.0.0.1:8080 http://example.com curl -x http://127.0.0.1:8080 https://example.com
关键设计要点
- 线程安全:使用线程池管理并发连接
- 异常处理:所有网络操作都需要异常处理
- 缓冲区管理:合理的缓冲区大小至关重要
- 超时设置:防止代理服务器挂起
- 资源管理:使用try-with-resources确保连接关闭
这些案例覆盖了大多数代理服务器的基本需求,可以根据实际场景选择合适的实现方式并进一步扩展功能。
版权声明:NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
足球直播
足球直播
足球直播
篮球直播
篮球直播
篮球直播
NBA直播
NBA直播
NBA直播
CBA直播
CBA直播
CBA直播
亚冠直播
亚冠直播
亚冠直播
欧冠直播
欧冠直播
欧冠直播
英超直播
英超直播
英超直播
西甲直播
西甲直播
西甲直播
中超直播
中超直播
中超直播
足球直播
足球直播
足球直播
篮球直播
篮球直播
篮球直播
NBA直播
NBA直播
NBA直播
CBA直播
CBA直播
CBA直播
亚冠直播
亚冠直播
亚冠直播
欧冠直播
欧冠直播
欧冠直播
英超直播
英超直播
英超直播
西甲直播
西甲直播
西甲直播
中超直播
中超直播
中超直播
足球直播
足球直播
足球直播
篮球直播
篮球直播
篮球直播
NBA直播
NBA直播
NBA直播
CBA直播
CBA直播
CBA直播
亚冠直播
亚冠直播
亚冠直播
欧冠直播
欧冠直播
欧冠直播
英超直播
英超直播
英超直播
西甲直播
西甲直播
西甲直播
中超直播
中超直播
中超直播
足球直播
足球直播
足球直播
篮球直播
篮球直播
篮球直播
NBA直播
NBA直播
NBA直播
CBA直播
CBA直播
CBA直播
亚冠直播
亚冠直播
亚冠直播
欧冠直播
欧冠直播
欧冠直播
英超直播
英超直播
英超直播
西甲直播
西甲直播
西甲直播
中超直播
中超直播
中超直播
曼联直播
曼联直播
曼联直播
日职联直播
日职联直播
日职联直播
澳超直播
澳超直播
澳超直播
阿森纳直播
阿森纳直播
阿森纳直播
足球直播
足球直播
足球直播
NBA直播
NBA直播
NBA直播
曼联直播
曼联直播
曼联直播
日职联直播
日职联直播
日职联直播
澳超直播
澳超直播
澳超直播
阿森纳直播
阿森纳直播
阿森纳直播
足球直播
足球直播
足球直播
NBA直播
NBA直播
NBA直播
曼联直播
曼联直播
曼联直播
日职联直播
日职联直播
日职联直播
澳超直播
澳超直播
澳超直播
阿森纳直播
阿森纳直播
阿森纳直播
足球直播
足球直播
足球直播
NBA直播
NBA直播
NBA直播
曼联直播
曼联直播
曼联直播
日职联直播
日职联直播
日职联直播
澳超直播
澳超直播
澳超直播
阿森纳直播
阿森纳直播
阿森纳直播
足球直播
足球直播
足球直播
NBA直播
NBA直播
NBA直播
欧冠直播
欧冠直播
欧冠直播
欧冠直播
欧冠直播
欧冠直播
欧冠直播
欧冠直播
欧冠直播
欧冠直播
欧冠直播
欧冠直播
欧冠直播
欧冠直播
欧冠直播
欧冠直播
欧冠直播
欧冠直播
欧冠直播
欧冠直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
足球直播
足球直播
足球直播
足球直播
足球直播
英超直播
英超直播
英超直播
英超直播
英超直播
篮球直播
篮球直播
篮球直播
篮球直播
篮球直播
CBA直播
CBA直播
CBA直播
CBA直播
CBA直播
中超直播
中超直播
中超直播
中超直播
中超直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
足球直播
足球直播
足球直播
足球直播
足球直播
英超直播
英超直播
英超直播
英超直播
英超直播
篮球直播
篮球直播
篮球直播
篮球直播
篮球直播
CBA直播
CBA直播
CBA直播
CBA直播
CBA直播
中超直播
中超直播
中超直播
中超直播
中超直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播