Java 与代理的输入/输出流混淆

Java 与代理的输入/输出流混淆,java,proxy,stream,Java,Proxy,Stream,试图用Java编写一个非常简单、简单的线程HTTP代理服务器,以及 我取得了很好的进步: 客户端连接到服务器、输入和输出 流到客户端 目标URL是从GET请求中提取的 与目标web服务器建立连接,并建立inputstream 现在我知道我需要发送来自服务器inputstream的数据并转发 它可以发送到客户端outputstream,但我不知道如何准确地执行此操作。我经验的扩展 对于输入和输出流,一直在发送单个字符串,我没有一个固定的 了解这些流是如何工作的 我是否应该将输入流中的所有数据读取到

试图用Java编写一个非常简单、简单的线程HTTP代理服务器,以及 我取得了很好的进步:

  • 客户端连接到服务器、输入和输出 流到客户端

  • 目标URL是从GET请求中提取的

  • 与目标web服务器建立连接,并建立inputstream

  • 现在我知道我需要发送来自服务器inputstream的数据并转发 它可以发送到客户端outputstream,但我不知道如何准确地执行此操作。我经验的扩展 对于输入和输出流,一直在发送单个字符串,我没有一个固定的 了解这些流是如何工作的

    我是否应该将输入流中的所有数据读取到一个文件中,然后写入输出流?有更优雅的解决方案吗

    这是我的密码:

    import java.io.*;
    import java.net.*;
    import java.util.*;
    
    public class Proxy {
    
    /////////////////////////////////////
    public static void go(){
    
    int incomingport = 50000;
    ServerSocket myproxysocket = null;
    
    try{
    myproxysocket = new ServerSocket(incomingport);
    while(true){
    System.out.println("HTTP Java Proxy Server");
    System.out.println();
    System.out.println("Listening on port 50000...Press CTRL+C to exit");
    System.out.println();
    Socket client = myproxysocket.accept();
    Thread t = new Thread(new ClientHandler(client));
    t.start();
    }//end while
    }//end try
    
    catch(Exception E){
    E.printStackTrace();    
    }
    }//end method go()
    
    ///////////////////////////////////
    public static void main(String args[]) {
    
    Proxy myserver =  new Proxy();
    myserver.go();
    
    }//end main
    }//end class proxy
    
    
    /////////////////////////////////////////////////////////////////////////////////////
    class ClientHandler implements Runnable{
    
    private final DataInputStream clientin;
    private final DataOutputStream clientout;
    private final Socket clientSocket;
    
    
    //constructor----------------
    public ClientHandler(Socket incomingSocket) throws IOException{
    
    clientSocket = incomingSocket; 
    clientin = new DataInputStream(incomingSocket.getInputStream());
    clientout = new DataOutputStream(incomingSocket.getOutputStream());
    
    
    }//--------------------------
    
    ////////////////////
    public void run(){
    try{
    
    //Get URL from client
    String getrequestline = clientin.readLine();
    String targetURL = null;
    String clientIP = null;
    StringTokenizer st = new StringTokenizer(getrequestline);
    st.nextToken();
    targetURL = st.nextToken();
    clientIP = clientSocket.getRemoteSocketAddress().toString();
    System.out.println();
    System.out.println("IP: " + clientIP);
    System.out.println("Requested URL: " + targetURL);
    System.out.println();
    
    //connect to target URL
    URL url = new URL(targetURL);
    URLConnection targetconnection = url.openConnection();
    targetconnection.setDoInput(true);
    targetconnection.setDoOutput(false);
    
    
    InputStream is = targetconnection.getInputStream();
    
    //How do I read in from is and write out to clientout?
    
    //clientout.write(???????)
    
    }//try
    catch(Exception E){
     E.printStackTrace();
    }//catch
    finally{
    try{clientSocket.close();}
    catch(Exception ee){}
    }//finally
    }//end run----------
    
    }//end CLASS--------------------------------------------------------------------------
    

    中有一个非常整洁的实用程序类

    org.apache.commons.io.IOUtils
    
    这是来自commons io包。如果可以的话就用它。否则,一个简单的方法(不使用任何NIO内容)是:

    public static void copy(InputStream is, OutputStream os) throws IOException {
        byte[] buff = new byte[1024*1024];
        int a = 0;
        while((a = is.read(buff)) > -1) {
    
            // a is the number of bytes ACTUALLY read, so 
            // when we write, that's the number of bytes to write
            os.write(buff,0,a);
        }
        os.flush();
    }
    

    和往常一样,不要忘记刷新。

    中有一个非常整洁的实用程序类

    org.apache.commons.io.IOUtils
    
    这是来自commons io包。如果可以的话就用它。否则,一个简单的方法(不使用任何NIO内容)是:

    public static void copy(InputStream is, OutputStream os) throws IOException {
        byte[] buff = new byte[1024*1024];
        int a = 0;
        while((a = is.read(buff)) > -1) {
    
            // a is the number of bytes ACTUALLY read, so 
            // when we write, that's the number of bytes to write
            os.write(buff,0,a);
        }
        os.flush();
    }
    

    和往常一样,别忘了冲洗。

    谢谢!。如果buff是一个字节数组,那么两个流之间到底发送了什么?它不是HTML吗?例如,当JSP在服务器上生成HTML时,它可以设置它的字符编码(或使用默认值)。然后使用此字符编码转换文本(可能包含多字节字符,如“你好") 在HTTP报头中,服务器还告诉客户端它使用的编码,以便客户端可以将其转换回实际字符。在这两者之间,它只是一堆字节,很像“.getBytes”(“utf-8”);将为您提供一个6字节的数组,但是”你好.getBytes(“utf-8”)将为您提供一个6字节的数组。你好 中文中的“hello”是2个字符,实际上(在utf-8中)转换为6个字节。因为您的代理不必知道实际的字符(它不必显示它们),您可以只复制原始字节。如果您想了解字符,您必须读取标题,找出字符编码,解码字节,然后再次执行相同的操作(在另一侧发送头,然后使用相同的字符编码将字符编码为字节。还有一个问题:用于连接到代理的端口不断从50000上升,即使在重新启动代理后也是如此。目前已达到62000左右的端口。是否需要关闭套接字?如果重新启动代理,即当VM ex如果buff是一个字节数组,那么两个流之间到底发送了什么?它不是HTML吗?例如,当JSP在服务器上生成HTML时,它可以设置其字符编码(或使用默认值)。然后使用此字符编码转换文本(可能包含多字节字符,例如“你好") 在HTTP报头中,服务器还告诉客户端它使用的编码,以便客户端可以将其转换回实际字符。在这两者之间,它只是一堆字节,很像“.getBytes”(“utf-8”);将为您提供一个6字节的数组,但是”你好.getBytes(“utf-8”)将为您提供一个6字节的数组。你好 中文中的“hello”是2个字符,实际上(在utf-8中)转换为6个字节。因为您的代理不必知道实际的字符(它不必显示它们),您可以只复制原始字节。如果您想了解字符,您必须读取标题,找出字符编码,解码字节,然后再次执行相同的操作(在另一侧发送头,然后使用相同的字符编码将字符编码为字节。还有一个问题:用于连接到代理的端口不断从50000上升,即使在重新启动代理后也是如此。目前已达到62000左右的端口。是否需要关闭套接字?如果重新启动代理,即当VM ex它的,这些应该被自动释放。