2010-03-29 11 views
6

Sto cercando di illustrare l'algoritmo Nagle in un semplice programma client-server. Ma non riesco a capirlo bene, o farselo stampare chiaramente.Illustrazione Java e Nagle

Nel mio esempio, il client genera solo int da 1 a 1024 e li invia al server. Il server converte semplicemente questi int in una stringa esadecimale e li rimanda al client.

Praticamente tutto quello che ho cambiato finisce con gli stessi risultati. Gli int sono inviati e inviati in blocchi di 256 int .. Ho provato setTcpNoDelay (true) su entrambi i lati per vedere un cambiamento ma questo dà lo stesso risultato nella mia console. (ma non in wireshark, vedo una grande differenza nella quantità di pacchetti inviati tra server e client) Ma il mio obiettivo è quello di essere in grado di vederlo nella console, immagino ci sia un buffer di ObjectOutputStream o simile che contiene tutto su?

Quando cambio output = new PrintWriter(client.getOutputStream(), true)-false(Il true o false: autoFlush - Un valore booleano, se true, i println, printf, o format metodi saranno svuotare il buffer di uscita) il mio server non fornisce alcuna uscita posteriore al cliente più.

Fondamentalmente il mio obiettivo è quello di dare solo true o false con server e/o client come argomento per impostare il TcpNoDelay, una volta avviato, per vedere chiaramente la differenza di input/output nella console. Non sono sicuro di tutto ciò che è stato usato, quindi qualsiasi aiuto per chiarirlo è il benvenuto.

Il server:

package Networks.Nagle; 

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

public class NagleDemoServer 
{ 
    private static ServerSocket serverSocket; 
    private static final int PORT = 1234; 

    public static void main(String[] args) throws IOException 
    { 
     int received = 0; 
     String returned; 
     ObjectInputStream input = null; 
     PrintWriter output = null; 
     Socket client; 

     try 
     { 
      serverSocket = new ServerSocket(PORT); 
      System.out.println("\nServer started..."); 
     } 
     catch (IOException ioEx) 
     { 
      System.out.println("\nUnable to set up port!"); 
      System.exit(1); 
     } 

     while(true) 
     { 
      client = serverSocket.accept(); 
      client.setTcpNoDelay(true); 

      System.out.println("\nNew client accepted.\n"); 

      try 
      { 
       input = new ObjectInputStream(client.getInputStream()); 
       output = new PrintWriter(client.getOutputStream(), true); 

       while(true) 
       { 
        received = input.readInt(); 
        returned = Integer.toHexString(received); 
        System.out.print(" " + received); 
        output.println(returned.toUpperCase()); 

       } 
      } 
      catch(EOFException eofEx) 
      { 
       output.flush(); 
       System.out.println("\nEnd of client data.\n"); 
      } 
      catch(SocketException sEx) 
      { 
       System.out.println("\nAbnormal end of client data.\n"); 
      } 
      catch(IOException ioEx) 
      { 
       ioEx.printStackTrace(); 
      } 

      input.close(); 
      output.close(); 
      client.close(); 
      System.out.println("\nClient closed.\n"); 
     } 
    } 
} 

Il cliente:

package Networks.Nagle; 

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

public class NagleDemoClient 
{ 
    private static InetAddress host; 
    private static final int PORT = 1234; 

    public static void main(String[] args) 
    { 
     Socket socket = null; 

     try 
     { 
      host = InetAddress.getByName("localhost"); 

      socket = new Socket(host, PORT); 

      socket.setTcpNoDelay(true); 
      socket.setSendBufferSize(64); 

      System.out.println("Send Buffer: " + socket.getSendBufferSize()); 
      System.out.println("Timeout: " + socket.getSoTimeout()); 
      System.out.println("Nagle deactivated: " + socket.getTcpNoDelay()); 

     } 
     catch(UnknownHostException uhEx) 
     { 
      System.out.println("\nHost ID not found!\n"); 
      System.exit(1); 
     } 
     catch(SocketException sEx) 
     { 
      sEx.printStackTrace(); 
     } 
     catch(IOException ioEx) 
     { 
      ioEx.printStackTrace(); 
     } 

     NagleClientThread client = new NagleClientThread(socket); 
     NagleReceiverThread receiver = new NagleReceiverThread(socket); 

     client.start(); 
     receiver.start(); 

     try 
     { 
      client.join(); 
      receiver.join(); 

      socket.close(); 
     } 
     catch(InterruptedException iEx) 
     { 
      iEx.printStackTrace(); 
     } 
     catch(IOException ioEx) 
     { 
      ioEx.printStackTrace(); 
     } 

     System.out.println("\nClient finished."); 
    } 
} 


class NagleClientThread extends Thread 
{ 
    private Socket socket; 

    public NagleClientThread(Socket s) 
    { 
     socket = s; 

    } 

    public void run() 
    { 
     try 
     { 
      ObjectOutputStream output = new ObjectOutputStream(socket.getOutputStream()); 

      for(int i = 1; i < 1025; i++) 
      { 
       output.writeInt(i); 
       sleep(10); 
      } 

      output.flush(); 
      sleep(1000); 
      output.close(); 
     } 
     catch(IOException ioEx) 
     { 
      ioEx.printStackTrace(); 
     } 
     catch(InterruptedException iEx) 
     { 
      iEx.printStackTrace(); 
     } 
    } 
} 


class NagleReceiverThread extends Thread 
{ 
    private Socket socket; 

    public NagleReceiverThread(Socket s) 
    { 
     socket = s; 
    } 

    public void run() 
    { 
     String response = null; 
     BufferedReader input = null; 

     try 
     { 
      input = new BufferedReader(
         new InputStreamReader(socket.getInputStream())); 

      try 
      { 
       while(true) 
       { 
        response = input.readLine(); 
        System.out.print(response + " "); 
       } 
      } 
      catch(Exception e) 
      { 
       System.out.println("\nEnd of server data.\n"); 
      }  

      input.close(); 

     } 
     catch(IOException ioEx) 
     { 
      ioEx.printStackTrace(); 
     } 
    } 
} 

risposta

0

Non sarà in grado di vedere la differenza perché readLine() attenderà fino a quando un EOL viene letto. Per vedere la differenza, usa i dati binari. Rendi i blocchi di scrittura del flusso in uscita di 64 byte separati da 10 ms di spazio. Fai in modo che il flusso in entrata legga blocchi di 1024 byte. Quando tcpNoDelay è true, il flusso in ingresso verrà letto circa 64 byte ad ogni operazione di lettura. Quando tcpNoDelay è falso, il flusso in ingresso leggerà molti più byte. È possibile registrare il numero medio di byte letti in ogni operazione di lettura, quindi la differenza è ovvia. E inoltre, prova sempre usando due macchine, perché il sistema operativo può ottimizzare i flussi di loopback.

+0

È possibile testare con un peer solo l'invio e un altro appena ricevuto e loggato. Ma sulla base del tuo esempio, capisco che tu voglia un viaggio del server per scopi di benchmarking. In tal caso, lasciare sempre attivo il server con tcpNoDelay e farlo leggere un blocco di 4096 byte e rispondere prontamente con il numero di byte che ha appena letto. Vedrai la differenza semplicemente variando tcpNoDelay sul client. – fernacolo