Permalänk
Medlem

Webproxy i Java

Jag försöker göra en webproxy i Java baserat på koden från
http://www.java2s.com/Code/Java/Network-Protocol/Asimpleproxy...

Men jag har ett problem med när jag hämtar remote host.
Jag kan hämta websidor genom proxyn om jag sätter ip-adressen till en websida direkt i koden, men då kan jag bara hämta den sidan och jag vill så klart kunna besöka alla siter.
Jag hittade ett sätt att för programmet att läsa in adressen själv, men då får jag time out på alla anslutningsförsök och jag vet inte varför.

Den fungerade koden med fast adress:

import java.io.IOException; import java.io.InputStream; import javax.swing.JTextArea; import java.io.OutputStream; import java.io.PrintWriter; import java.net.InetAddress; import java.net.ServerSocket; import java.net.Socket; import java.net.UnknownHostException; public class ProxyThread extends Thread { private String host; private int remoteport; private int localport; private JTextArea log; public ProxyThread(int remoteport, int localport, JTextArea log) { this.remoteport = remoteport; this.localport = localport; this.log = log; } /** * runs a single-threaded proxy server on the specified local port. It never * returns. */ public void run() { while (true) { try { InetAddress addr = InetAddress.getLocalHost(); // Get IP Address byte[] ipAddr = addr.getAddress(); // Get hostname this.host = addr.getHostName(); } catch (UnknownHostException e) { } // Create a ServerSocket to listen for connections with ServerSocket ss; try { ss = new ServerSocket(localport); final byte[] request = new byte[1024]; byte[] reply = new byte[4096]; while (true) { Socket client = null, server = null; try { // Wait for a connection on the local port client = ss.accept(); final InputStream streamFromClient = client .getInputStream(); final OutputStream streamToClient = client .getOutputStream(); host = "74.125.77.147"; try { server = new Socket(host, remoteport); } catch (IOException e) { log.append("\nProxy server cannot connect to " + host + ":" + remoteport + ":\n" + e + "\n"); System.out.println("\nProxy server cannot connect to " + host + ":" + remoteport + ":\n" + e + "\n"); PrintWriter out = new PrintWriter(streamToClient); out.print("Proxy server cannot connect to " + host + ":" + remoteport + ":\n" + e + "\n"); out.flush(); client.close(); continue; } // Get server streams. final InputStream streamFromServer = server .getInputStream(); final OutputStream streamToServer = server .getOutputStream(); System.out.println("Anslöt, server Inetaddress: " + server.getInetAddress().toString()); // a thread to read the client's requests and pass them // to the server. A separate thread for asynchronous. Thread t = new Thread() { public void run() { int bytesRead; try { while ((bytesRead = streamFromClient .read(request)) != -1) { streamToServer.write(request, 0, bytesRead); streamToServer.flush(); } } catch (IOException e) { log.append("\n" + e.toString()); } // the client closed the connection to us, so // close our // connection to the server. try { streamToServer.close(); } catch (IOException e) { log.append("\n" + e.toString()); } } }; // Start the client-to-server request thread running t.start(); // Read the server's responses // and pass them back to the client. int bytesRead; try { while ((bytesRead = streamFromServer.read(reply)) != -1) { streamToClient.write(reply, 0, bytesRead); streamToClient.flush(); } } catch (IOException e) { log.append("\n" + e.toString()); } // The server closed its connection to us, so we close // our // connection to our client. streamToClient.close(); } catch (IOException e) { log.append("\n" + e.toString()); } finally { try { if (server != null) server.close(); if (client != null) client.close(); } catch (IOException e) { log.append("\n" + e.toString()); } } } } catch (IOException e) { // TODO Auto-generated catch block log.append("\n" + e.toString()); } } }

Google hämtas i browsern och i consolen står det:
Anslöt, server Inetaddress: /74.125.77.147

Om jag byter ut host = "74.125.77.147"; i koden ovan mot:

final InputStream streamFromClient = client .getInputStream(); final OutputStream streamToClient = client .getOutputStream(); BufferedReader in = new BufferedReader( new InputStreamReader(streamFromClient)); String line = in.readLine(); int lastSpace = line.lastIndexOf(' '); // Läs urlen från GET URL url = new URL(line.substring(4, lastSpace)); host = url.getHost(); System.out.println(host.toString());

Så får jag connection reset i browsern och i consolen står det:
www.google.se
Anslöt, server Inetaddress: www.google.se/66.102.13.106

server = new Socket(host, remoteport); måste fungera i båda fallen då jag inte får syso-meddelandet i catch-delen.
Men sen går något fel eftersom jag får connection reset.

Permalänk

Vad du gör med ditt tillägg i koden är att du läser ut den första raden som skickas från klienten.

När du sedan kommer till delen i ditt program där det står

while ((bytesRead = streamFromClient.read(request)) != -1) { streamToServer.write(request, 0, bytesRead); streamToServer.flush(); }

så ska förfrågan från klienten skickas vidare till servern, men första raden saknas och förfrågan kommer att misslyckas.

En bättre idé är att du läser ut hela förfrågan från klienten där du nu läser första raden:

int totalBytesRead = 0; while ((bytesRead = streamFromClient.read(request, totalBytesRead, 4096 - totalBytesRead)) != -1) { totalBytesRead += bytesRead; }

Sen läser du ut första raden från request arrayen:

BufferedReader in = new BufferedReader(new ByteArrayInputStream(request)); String line = in.readLine();

Och använder den för att ta ut URLen som du redan gjort. Sen skickar du vidare hela förfrågan till servern:

streamToServer.write(request, 0, totalBytesRead); streamToServer.flush();

Permalänk
Medlem

När jag skriver

int totalBytesRead = 0; while ((bytesRead = streamFromClient.read(request, totalBytesRead, 4096 - totalBytesRead)) != -1) { totalBytesRead += bytesRead; }

får jag ett arrayIndexOutOfBoundsException.
Jag provade att ändra 4096 till 1024, då får jag inga exceptions men programmet går inte vidare.
Jag la till System.out.println(bytesRead + " " + totalBytesRead); i while-satsen och får bara en utskrift som är 883 0.

Permalänk

Hmm ok, testa det här istället

ByteArrayOutputStream buf = new ByteArrayOutputStream(); while ((bytesRead = streamFromClient.read(request)) != -1) { buf.write(request, 0, bytesRead); } byte[] completeRequest = buf.toByteArray();

Och använd completeRequest istället för request senare. Jag har inte testat den här koden heller, men om du funderar lite på vad som händer så borde du kunna få till det.

Permalänk
Medlem

Jag får samma problem som tidigare, while-loopen körs en gång och stannar när den borde fortsätta.
När jag kör följande kod

ByteArrayOutputStream buf = new ByteArrayOutputStream(); while ((bytesRead = streamFromClient.read(request)) != -1) { buf.write(request, 0, bytesRead); System.out.println("bytesRead = " + bytesRead); if(bytesRead != -1){ System.out.println("bytesRead är inte -1 och while-loopen borde fortsätta."); } }

får jag denna utskrift
bytesRead = 909
bytesRead är inte -1 och while-loopen borde fortsätta.