2013-10-06 2 views
0

Ma tâche de programmation nécessite que je crée un proxy entre le client et le serveur. Mon client envoie une requête au serveur via le proxy, puis le proxy le transmet et renvoie la réponse du serveur au client.Proxy en Java - le client n'affiche pas la réponse?

Voici les étapes de mon travail:

1) obtenir la demande du client et stocker les données de demande dans un tableau d'octets

2) lu à partir du tableau d'octets en utilisant BufferedReader

3) Inscrivez-vous le nom d'hôte de l'hôte: champ d'en-tête et créer une serverSocket avec elle

4) transmet les données de demande à la serverSocket outputstream

5) récupérer les données de réponse à partir du inputstream de serverSocket dans un autre tableau d'octets

6) écrire le contenu du tableau d'octets dans le flux de sortie de clientSocket

Cependant, après l'étape 6, le navigateur ne peut pas afficher les données de réponse . De l'aide?

import java.io.*; 
import java.net.*; 
import java.util.*; 

public class proxy2 { 

    public static void main(String args[]) throws Exception 
    { 
    int port = Integer.parseInt(args[0]); 
    File fileSub= new File(args[1]); //fileSub 
    File fileRediect = new File(args[2]); //fileRedirect 

    ServerSocket listener = new ServerSocket(port); 


    while (true) { 
     proxy_func(listener.accept()); 

    } 

    } 

    public static void proxy_func(Socket clientSocket) throws Exception{ 

    OutputStream outputToClient = clientSocket.getOutputStream(); 

    //store clientSocket's inputstream into a buffer 
    ByteArrayOutputStream buffer = new ByteArrayOutputStream(); 
    int nRead; //start offset in the data 
    byte[] data = new byte[16384]; //create byte array 
    //read each byte from InputStream and write it to a ByteArrayOutputStream 
    while((nRead = clientSocket.getInputStream().read(data, 0, data.length)) != -1) { 
     buffer.write(data, 0, nRead); 
    } 
    buffer.flush(); //forces any buffered bytes to be written out 
    data = buffer.toByteArray(); //retrieve the underlying byte array 
    System.out.println(new String(data)); 

    //create buffer reader for clientSocket's inputstream 
    InputStream inputStream = new ByteArrayInputStream(data); 
    BufferedReader readFromClient = new BufferedReader(new InputStreamReader(inputStream)); 

    String[] strArr; 
    String line; 
    String hostname = null; 

    //get hostname 
    while( (line=readFromClient.readLine()) != null) 
    { 
     strArr = line.split(" "); 
     if(strArr[0].equals("Host:")) 
     hostname = strArr[1]; 
    } 
    System.out.println("Host: " + hostname); 

    //create server socket 
    Socket serverSocket = new Socket(hostname, 80); 
    OutputStream outputToServer = serverSocket.getOutputStream(); 
    InputStream inputFromServer = serverSocket.getInputStream(); 

    //forward request to server 
    System.out.println("forward request to server..."); 
    outputToServer.write(data); 

    //receive data from server and write response back to client 
    byte[] receivedData = new byte[16384]; 
    int size; 
    while((size = inputFromServer.read(receivedData)) != -1) 
    { 
     System.out.println("write response back to client..."); 
     System.out.println("size: " + size); 
     System.out.println(new String(receivedData)); 
     outputToClient.write(receivedData, 0, size); 
    } 

    System.out.println("flushing..."); 
    outputToClient.flush(); 
    outputToClient.close(); 
    } 
} 

Donc, fondamentalement, je suivre cette mise en page pour les E/S:

{ 
    OutputStream outputToClient = clientSocket.getOutputStream(); 
    BufferedReader readFromClient = new BufferedReader(new InputStreamReader(clientSocket.getInputStream())); 

    //step 1 
    //get the HTTP request header from your firefox 
    String line = readFromClient.readLine(); 

    //if the Content_Length within the HTTP header exists and not equals to 0 
    char [] buffer = new char [#]; 
    readFromClient.read(buffer, 0, Content_Length); //get the body message 

    OutputStream outputToServer = serverSocket.getOutputStream(); 
    InputStream inputFromServer = serverSocket.getInputStream(); 
    //step 2 
    outputToServer.write(Bytes[]) //forword the HTTP requests to server host. 

    //step 3 
    byte[] data = new byte[#]; 
    while ((size = inputFromServer.read(data)) != -1) //get the response data from server 
    { 
     //step 4 
     outputToClient.write(data, 0, size); //forward the data to your firefox 
    } 
} 

Répondre

0

Ok, j'ai trouvé la cause du problème. Ma boucle while a été bloquée car je n'ai pas détecté la fin de la requête HTTP. Cette réponse adresse mon problème succintement: https://stackoverflow.com/a/9542710

Juste poster ici pour ceux qui ont trébuché sur ce problème et se sont perdus.

Voici mon code mis à jour qui peut fonctionner (notez que j'ai ajouté une méthode pour détecter la fin de la requête HTTP):

import java.io.*; 
import java.net.*; 
import java.util.*; 

public class proxy2 { 

    public static void main(String args[]) throws Exception 
    { 
    int port = Integer.parseInt(args[0]); 
    File fileSub= new File(args[1]); //fileSub 
    File fileRediect = new File(args[2]); //fileRedirect 

    //create listener socket to listen for requests from browser 
    ServerSocket listener = new ServerSocket(port); 

    while (true) { 
     proxy_func(listener.accept()); 
    } 

    } 

    public static void proxy_func(Socket clientSocket) throws Exception{ 

    OutputStream outputToClient = clientSocket.getOutputStream(); 
    InputStream inputFromClient = clientSocket.getInputStream(); 

    //store clientSocket's inputstream into a buffer 

    ByteArrayOutputStream buffer = new ByteArrayOutputStream(); 
    int nRead; //start offset in the data 
    byte[] data = new byte[16384]; 
    //read each byte from InputStream and write it to a ByteArrayOutputStream 
    while((nRead = inputFromClient.read(data, 0, data.length)) != -1) { 
     System.out.println("reading from client..."); 
     buffer.write(data, 0, nRead); 
     //if reached end of HTTP request, break out of this loop 
     if(endOfRequest(data) == true) 
     break; 
    } 
    buffer.flush(); //forces any buffered bytes to be written out 
    data = buffer.toByteArray(); //retrieve the underlying byte array 
    System.out.println(new String(data)); 

    //create buffered reader for byte array input stream (request data) 
    InputStream inputStream = new ByteArrayInputStream(data); 
    BufferedReader readFromClient = new BufferedReader(new InputStreamReader(inputStream)); 

    String[] strArr; 
    String line; 
    String hostname = null; 

    //get hostname 
    while( (line=readFromClient.readLine()) != null) 
    { 
     strArr = line.split(" "); 
     if(strArr[0].equals("Host:")) 
     hostname = strArr[1]; 
    } 
    System.out.println("Host: " + hostname); 

    //create server socket 
    Socket serverSocket = new Socket(hostname, 80); 
    OutputStream outputToServer = serverSocket.getOutputStream(); 
    //InputStream inputFromServer = serverSocket.getInputStream(); 

    //forward request to server 
    System.out.println("forward request to server..."); 
    outputToServer.write(data); 

    //receive data from server and write response back to client 
    DataInputStream inputFromServer = new DataInputStream(serverSocket.getInputStream()); 
    byte[] receivedData = new byte[1024]; 
    int size; 
    while((size = inputFromServer.read(receivedData, 0, receivedData.length)) != -1) 
    { 
     System.out.println("write response back to client..."); 
     System.out.println(new String(receivedData)); 
     outputToClient.write(receivedData, 0, size); 
     outputToClient.flush(); 
    } 

    System.out.println("done sending"); 
    outputToClient.close(); 
    } 

    //method to detect end of HTTP request 
    //return true if detected, otherwise false 
    public static boolean endOfRequest(byte[] data) throws Exception 
    { 
    System.out.println("parsing request.."); 
    BufferedReader br = new BufferedReader(new InputStreamReader(new ByteArrayInputStream(data))); 
    String line; 

    while((line=br.readLine()) != null) { 
     if (line.equals("")) 
     return true; 
    } 
    return false; 
    } 
} 
1

Il y a un problème dans la dernière partie:

byte[] receivedData = new byte[16384]; 
int size; 
while((size = inputFromServer.read(receivedData)) != -1) 
{ 
    System.out.println("write response back to client..."); 
    System.out.println("size: " + size); 
    System.out.println(new String(receivedData)); 
} 
outputToClient.write(receivedData); 

Alors, disons que le serveur renvoie 1 million d'octets. La boucle les lit par morceaux de 16384 octets, et une fois qu'il a lu tous les morceaux, il renvoie ce qui a été laissé dans le tampon receivedData par l'après la dernière lecture. Ainsi, le navigateur ne recevra que 16384 octets parmi les 1.000.000 octets envoyés par le serveur.

Vous devez envoyer tout ce que vous lisez à partir du serveur au navigateur:

byte[] receivedData = new byte[16384]; 
int size; 
while((size = inputFromServer.read(receivedData)) != -1) 
{ 
    System.out.println("write response back to client..."); 
    System.out.println("size: " + size); 
    System.out.println(new String(receivedData)); 
    outputToClient.write(receivedData, 0, size);  
} 
+0

Hey merci pour votre réponse. En fait, j'ai mis en place votre approche avant mais cela n'a pas fonctionné. J'ai mis à jour ma réponse avec votre code édité. Connaissez-vous d'autres façons de faire ce travail? – uohzxela

+0

Définir "n'a pas fonctionné". Ce qui se produit. Que disent vos journaux? Que voyez-vous la console réseau Firebug? –

+0

Je peux voir les données de réponse imprimées sur la console (j'ai couru en utilisant cmd), mais mon navigateur est incapable d'afficher les données de réponse, c'est-à-dire qu'il attend toujours la réponse. – uohzxela

0

Vous faites tout faux. Un proxy HTTP doit seulement lire la commande CONNECT et l'actionner. Après cela, il suffit de copier les octets dans les deux directions simultanément aussi vite que possible. Plus vous essayez de comprendre le protocole HTTP dans le proxy, plus vous introduisez de bogues.