在这些示例中,您可以找到创建简单代理套接字服务器的不同方法。由于多种原因,这对您很有用:
- 捕获客户端和服务器之间的流量。
- 限制上传/下载带宽,以了解您的网站是如何加载慢速连接的。
- 查看网络出现问题时系统的反应。
- "动态"修改客户端/服务器的内容(发送的接收)。
- 生成有关流量的统计信息。
*您可以使用此处的示例作为开发的基础。尚未实现任何功能。以下示例只是代理。您不能总是将它们用作 HTTP 代理。
示例 1
import java.io.*;
import java.net.*;
/**
*
* @author jcgonzalez.com
*
*/
public class ProxyMultiThread {
public static void main(String[] args) {
try {
if (args.length != 3)
throw new IllegalArgumentException("insuficient arguments");
// and the local port that we listen for connections on
String host = args[0];
int remoteport = Integer.parseInt(args[1]);
int localport = Integer.parseInt(args[2]);
// Print a start-up message
System.out.println("Starting proxy for " + host + ":" + remoteport + " on port " + localport);
ServerSocket server = new ServerSocket(localport);
while (true) {
new ThreadProxy(server.accept(), host, remoteport);
}
} catch (Exception e) {
System.err.println(e);
System.err.println("Usage: java ProxyMultiThread " + "<host> <remoteport> <localport>");
}
}
}
/**
* Handles a socket connection to the proxy server from the client and uses 2
* threads to proxy between server and client
*
* @author jcgonzalez.com
*
*/
class ThreadProxy extends Thread {
private Socket sClient;
private final String SERVER_URL;
private final int SERVER_PORT;
ThreadProxy(Socket sClient, String ServerUrl, int ServerPort) {
this.SERVER_URL = ServerUrl;
this.SERVER_PORT = ServerPort;
this.sClient = sClient;
this.start();
}
@Override
public void run() {
try {
final byte[] request = new byte[1024];
byte[] reply = new byte[4096];
final InputStream inFromClient = sClient.getInputStream();
final OutputStream outToClient = sClient.getOutputStream();
Socket client = null, server = null;
// connects a socket to the server
try {
server = new Socket(SERVER_URL, SERVER_PORT);
} catch (IOException e) {
PrintWriter out = new PrintWriter(new OutputStreamWriter(outToClient));
out.flush();
throw new RuntimeException(e);
}
// a new thread to manage streams from server to client (DOWNLOAD)
final InputStream inFromServer = server.getInputStream();
final OutputStream outToServer = server.getOutputStream();
// a new thread for uploading to the server
new Thread() {
public void run() {
int bytes_read;
try {
while ((bytes_read = inFromClient.read(request)) != -1) {
outToServer.write(request, 0, bytes_read);
outToServer.flush();
// TODO CREATE YOUR LOGIC HERE
}
} catch (IOException e) {
}
try {
outToServer.close();
} catch (IOException e) {
e.printStackTrace();
}
}
}.start();
// current thread manages streams from server to client (DOWNLOAD)
int bytes_read;
try {
while ((bytes_read = inFromServer.read(reply)) != -1) {
outToClient.write(reply, 0, bytes_read);
outToClient.flush();
// TODO CREATE YOUR LOGIC HERE
}
} catch (IOException e) {
e.printStackTrace();
} finally {
try {
if (server != null)
server.close();
if (client != null)
client.close();
} catch (IOException e) {
e.printStackTrace();
}
}
outToClient.close();
sClient.close();
} catch (IOException e) {
e.printStackTrace();
}
}
}
编译和使用
javac ProxyMultiThread.java
java ProxyMultiThread 192.168.1.10 8080 9999
在端口 9999 上启动 192.168.1.10:8180 的代理
(现在流量通过代理从localhost 9999重定向到192.168.1.10。请记住,由于HTTP主机标签,引用程序,javascript重定向等原因,Web浏览器可能并不总是有效。
使用示例 1 作为另一个 HTTP 代理的 HTTP 代理
如果您的 HTTP 代理在端口380上myproxy.test.net,并且您希望在 java 到达代理之前使用 java 作为代理,则应按如下方式运行它。
java ProxyMultiThread myproxy.test.net 80 9999
现在调整浏览器配置以使用本地主机 9999 上的代理
在火狐浏览器中:
*现在,您的所有流量都应该先转到示例1,然后再转到您的代理。
示例 2
// This example is from _Java Examples in a Nutshell_. (http://www.oreilly.com)
// Copyright (c) 1997 by David Flanagan
// This example is provided WITHOUT ANY WARRANTY either expressed or implied.
// You may study, use, modify, and distribute it for non-commercial purposes.
// For any commercial use, see http://www.davidflanagan.com/javaexamples
import java.io.*;
import java.net.*;
/**
* This class implements a simple single-threaded proxy server.
**/
public class SimpleProxyServer {
/** The main method parses arguments and passes them to runServer */
public static void main(String[] args) throws IOException {
try {
// Check the number of arguments
if (args.length != 3)
throw new IllegalArgumentException("Wrong number of arguments.");
// Get the command-line arguments: the host and port we are proxy for
// and the local port that we listen for connections on
String host = args[0];
int remoteport = Integer.parseInt(args[1]);
int localport = Integer.parseInt(args[2]);
// Print a start-up message
System.out.println("Starting proxy for " + host + ":" + remoteport + " on port " + localport);
// And start running the server
runServer(host, remoteport, localport); // never returns
} catch (Exception e) {
System.err.println(e);
System.err.println("Usage: java SimpleProxyServer " + "<host> <remoteport> <localport>");
}
}
/**
* This method runs a single-threaded proxy server for host:remoteport on the
* specified local port. It never returns.
**/
public static void runServer(String host, int remoteport, int localport) throws IOException {
// Create a ServerSocket to listen for connections with
ServerSocket ss = new ServerSocket(localport);
// Create buffers for client-to-server and server-to-client communication.
// We make one final so it can be used in an anonymous class below.
// Note the assumptions about the volume of traffic in each direction...
final byte[] request = new byte[1024];
byte[] reply = new byte[4096];
// This is a server that never returns, so enter an infinite loop.
while (true) {
// Variables to hold the sockets to the client and to the server.
Socket client = null, server = null;
try {
// Wait for a connection on the local port
client = ss.accept();
// Get client streams. Make them final so they can
// be used in the anonymous thread below.
final InputStream from_client = client.getInputStream();
final OutputStream to_client = client.getOutputStream();
// Make a connection to the real server
// If we cannot connect to the server, send an error to the
// client, disconnect, then continue waiting for another connection.
try {
server = new Socket(host, remoteport);
} catch (IOException e) {
PrintWriter out = new PrintWriter(new OutputStreamWriter(to_client));
out.println("Proxy server cannot connect to " + host + ":" + remoteport + ":\n" + e);
out.flush();
client.close();
continue;
}
// Get server streams.
final InputStream from_server = server.getInputStream();
final OutputStream to_server = server.getOutputStream();
// Make a thread to read the client's requests and pass them to the
// server. We have to use a separate thread because requests and
// responses may be asynchronous.
new Thread() {
public void run() {
int bytes_read;
try {
while ((bytes_read = from_client.read(request)) != -1) {
to_server.write(request, 0, bytes_read);
System.out
.println(bytes_read + "to_server--->" + new String(request, "UTF-8") + "<---");
to_server.flush();
}
} catch (IOException e) {
}
// the client closed the connection to us, so close our
// connection to the server. This will also cause the
// server-to-client loop in the main thread exit.
try {
to_server.close();
} catch (IOException e) {
}
}
}.start();
// Meanwhile, in the main thread, read the server's responses
// and pass them back to the client. This will be done in
// parallel with the client-to-server request thread above.
int bytes_read;
try {
while ((bytes_read = from_server.read(reply)) != -1) {
try {
Thread.sleep(1);
System.out.println(bytes_read + "to_client--->" + new String(request, "UTF-8") + "<---");
} catch (InterruptedException e) {
e.printStackTrace();
}
to_client.write(reply, 0, bytes_read);
to_client.flush();
}
} catch (IOException e) {
}
// The server closed its connection to us, so close our
// connection to our client. This will make the other thread exit.
to_client.close();
} catch (IOException e) {
System.err.println(e);
}
// Close the sockets no matter what happens each time through the loop.
finally {
try {
if (server != null)
server.close();
if (client != null)
client.close();
} catch (IOException e) {
}
}
} // while(true)
}
}
示例 3 HTTP 代理
我使用Benjamin Kohl&Artem Melnik的HTTP Java Proxy下载这里或转到原始网站这里.
笔记
- 您可以使用Thread.sleep来限制带宽,抛出随机异常以扰乱网络,修改内容等。