Java 创建带有套接字的简单代理服务器示例

在这些示例中,您可以找到创建简单代理套接字服务器的不同方法。由于多种原因,这对您很有用:

  • 捕获客户端和服务器之间的流量。
  • 限制上传/下载带宽,以了解您的网站是如何加载慢速连接的。
  • 查看网络出现问题时系统的反应。
  • "动态"修改客户端/服务器的内容(发送的接收)。
  • 生成有关流量的统计信息。

*您可以使用此处的示例作为开发的基础。尚未实现任何功能。以下示例只是代理。您不能总是将它们用作 HTTP 代理。

示例 1(多插槽代理服务器) 

使用示例 1 作为另一个 HTTP 代理的 HTTP 代理

示例 2(同时只有 1 个插槽)

示例 3 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 代理在端口380myproxy.test.net,并且您希望在 java 到达代理之前使用 java 作为代理,则应按如下方式运行它。

java ProxyMultiThread myproxy.test.net 80 9999

现在调整浏览器配置以使用本地主机 9999 上的代理

在火狐浏览器中:

img/0/87/settings.png

*现在,您的所有流量都应该先转到示例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来限制带宽,抛出随机异常以扰乱网络,修改内容等。
  • 3
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 1
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值