Buonasera a tutti, sto studiando i socket per l'università e sto cercando di esercitarmi ma con scarsi risultati.

Tutti gli esempi che ho trovato online lavorano con client e server che dopo aver inviato un solo messaggio effettuano una close().
Non riesco a capire come creare una socket con client e server che comunicano e scambiano diversi messaggi.
Ho provato a svolgere un esercizio e ci ho sbattuto la testa per giorni senza trovare la soluzione.. Qualcuno saprebbe dirmi cosa sbaglio?
Grazie

CLIENT

codice:
/*Scrivere in C o Java un programma che:apra una connessione verso "hocalhost", port 4020
invii la stringa "GET /gp/prova/11.aux\n"
nello stream di byte ricevuti individui la prima parentesi quadra aperta
memorizzi tutti i successivi byte fino alla prima parentesi quadra chiusa, che il server invierà, in una variabile stringa denominata "s"
riaperta la connessione, invii la stringa s (attenzione: dovrebbe terminare per "\n")
scriva i byte ricevuti in risposta sulla standard output*/


// Client


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


public class ClientSocket {	
	String response="";
	String messaggio = "GET /gp/prova/11.aux\n";
	String s="";
	
	boolean inviato = false;
	boolean salvato = false;
	
	
 public void run() {
	try {
		while(true){
			int serverPort = 4020;
			InetAddress host = InetAddress.getByName("localhost"); 
			System.out.println("Connecting to server on port " + serverPort); 


			Socket socket = new Socket(host,serverPort); //creo la socket con localhost, porta 4020
			//Socket socket = new Socket("127.0.0.1", serverPort);
			System.out.println("Just connected to " + socket.getRemoteSocketAddress()); 
			PrintWriter toServer = 				//inizializzo stream di output
				new PrintWriter(socket.getOutputStream(),true);
			BufferedReader fromServer = 			//inizializzo stream di input
				new BufferedReader( new InputStreamReader(socket.getInputStream()));
			
			if(!inviato){//se non ha ancora inviato la prima stringa dell'esercizio la invia
				toServer.println(messaggio); 
				inviato = true;		//setta inviato a true in modo tale da inviarla una sola volta
				String line = fromServer.readLine();
				System.out.println("Client received: " + line + " from Server"); //stampa cosa risponde il server
				response = line;
			}
			
			
		
			if(inviato == true && salvato == false){//se ho già inviato la stringa dell'esercizio e non ho ancora analizzato la risposta
				for(int i=0; i<response.length(); i++){ //scorro la risposta del server
					if(response.charAt(i) == '['){ //appena trovo una parentesi quadra salvo in s tutto il resto
						for(int j=i+1; response.charAt(j) != ']'; j++){
							s += response.charAt(j);
							salvato = true;	//imposto salvato a true per evitare di ripetere   l'operazione al prossimo ciclo
						}
					}
				}
			}
			
			if(salvato == true){		//se ho già salvato lo stream in s, invio s al server.
				s+="\n";	
				toServer.println(s);		//ma questa print non funziona... 
				System.out.println("Inviato: "+s);
				
				String line = fromServer.readLine();	//aspetto conferma dal server
				System.out.println("Client received: " + line + " from Server");
				
				if(line.equals("Esame superato")){		//se corretta chiudo stream e socket
					toServer.close();
					fromServer.close();
					socket.close();
				}else{														//se errata ripeto la procedura
					inviato = false;
					salvato = false;
				}
				
				
			}
		}
	}
	
	catch(UnknownHostException ex) {
		ex.printStackTrace();
	}
	catch(IOException e){
		e.printStackTrace();
	}
  }
	
  public static void main(String[] args) {
		ClientSocket client = new ClientSocket();
		client.run();
  }
}


SERVER

codice:
/*Scrivere in C o Java un programma che:apra una connessione verso "localhost", port 4020
invii la stringa "GET /gp/prova/11.aux\n"
nello stream di byte ricevuti individui la prima parentesi quadra aperta
memorizzi tutti i successivi byte fino alla prima parentesi quadra chiusa, che il server invierà, in una variabile stringa denominata "s"
riaperta la connessione, invii la stringa s (attenzione: dovrebbe terminare per "\n")
scriva i byte ricevuti in risposta sulla standard output*/


// Server Side
import java.net.*;
import java.io.*;


public class ServerSideSocket { 
  boolean inviato = false;	
	
  public void run() {
	try {
		int serverPort = 4020;
		ServerSocket serverSocket = new ServerSocket(serverPort);	//inizializzo serversocket con porta 4020
		serverSocket.setSoTimeout(10000); 		
		while(true) {
			System.out.println("Waiting for client on port " + serverSocket.getLocalPort() + "..."); 


			Socket server = serverSocket.accept();	//attendo connessioni
			System.out.println("Just connected to " + server.getRemoteSocketAddress()); 


			PrintWriter toClient = 				//inizializzo stream di output
				new PrintWriter(server.getOutputStream(),true);
			BufferedReader fromClient =			//inizializzo stream di input
				new BufferedReader(
						new InputStreamReader(server.getInputStream()));
			String line = fromClient.readLine();	 //leggo messaggio del client
			System.out.println("Server received: " + line); 
			if(!inviato){		//se non ho ancora inviato la stringa di risposta la invio
				toClient.println("aadsnaskdfhga[piccolastellasenzacielo]caosonosiadsjakjfbhbhs"); 
				inviato = true;
			}
			
			if(line.equals("piccolastellasenzacielo")){ //controllo se il client mi ha inviato la stringa che mi aspettavo
				
				toClient.println("Esame superato\n"); 	//comunico al client che la stringa è corretta
				System.out.println("Esame superato");
			
			}
		}
	}
	catch(UnknownHostException ex) {
		ex.printStackTrace();
	}
	catch(IOException e){
		e.printStackTrace();
	}
  }
	
  public static void main(String[] args) {
		ServerSideSocket srv = new ServerSideSocket();
		srv.run();
  }
}

Spero di aver commentato bene il codice.
Grazie ancora