从InputStream中提取内容

时间:2017-01-28 23:21:08

标签: java http proxy server

我的目标是创建一个可以执行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

1 个答案:

答案 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];
        }
    }
 }