我的目标是创建一个可以执行GET / POST请求的简单HTTP代理,尝试了解Java套接字。如果有人能指出我这个方向,我将不胜感激。
// 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.
Thread t = new Thread() {
public void run() {
int bytes_read;
try {
while((bytes_read = from_client.read(request)) != -1) {
to_server.write(request, 0, bytes_read);
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 the client-to-server request thread running
t.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) {
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) {}
}
}
}
}
从http://examples.oreilly.com/jenut/SimpleProxyServer.java
获取的代码我想知道如何从输入流中提取HOSTNAME并使用提取的信息传递给下面的方法。
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;
}
我已经尝试创建一个将InputStream转换为String格式的方法,但它似乎会在将程序分配给变量后使程序卡住。 (在这里尝试了类似的东西 - Read/convert an InputStream to a String)
答案 0 :(得分:1)
您可以创建单独的ByteArrayOutputStream
以获取InputStream
。
...
final OutputStream to_client= client.getOutputStream();
ByteArrayOutputStream baos = new ByteArrayOutputStream();
...
然后在while循环中,您也可以写入baos
...
while((bytes_read = from_server.read(reply)) != -1) {
to_client.write(reply, 0, bytes_read);
to_client.flush();
baos.write(reply, 0, bytes_read);
}
baos.flush();
...
最后你可以从baos
得到字符串。
String requestString = new String(baos.toByteArray());
然后,您可以通过以下方式搜索Host
标题:
String[] headers = requestString.split("\n");
for (int i = 0; i < headers.length; i++) {
if (headers[i].startsWith("Host")) {
String[] hostHeader = headers[i].split(":");
if (hostHeader.length > 1) {
host = hostHeader[1];
}
}
}