2010-03-29 5 views
6

J'essaie d'illustrer l'algorithme de Nagle dans un programme simple client-serveur. Mais je n'arrive pas à le comprendre ou à l'imprimer clairement.Illustration de Java et Nagle

Dans mon exemple, le client génère simplement des int de 1 à 1024 et les envoie au serveur. Le serveur convertit simplement ces int en une chaîne hexadécimale et les renvoie au client.

À peu près tout ce que je change finit avec les mêmes résultats. Les int sont envoyés et renvoyés dans des blocs de 256 int. J'ai essayé setTcpNoDelay (true) des deux côtés pour voir un changement mais cela donne le même résultat dans ma console. (mais pas dans wireshark, je vois une grande différence dans la quantité de paquets envoyés entre le serveur et le client) Mais mon but est de pouvoir le voir dans la console, je suppose qu'il y a du buffer d'ObjectOutputStream ou similaire en haut?

Quand je change output = new PrintWriter(client.getOutputStream(), true)-false(Le true ou false: autoFlush - Valeur booléenne, si true, les println, printf ou format méthodes videra le tampon de sortie) mon serveur ne donne pas de sortie de retour à la client plus. Fondamentalement mon but est juste de donner vrai ou faux avec le serveur et/ou le client comme argument pour régler le TcpNoDelay, quand il est démarré, pour voir clairement la différence d'entrée/sortie dans la console. Je ne suis pas sûr de tout ce qui est utilisé, donc toute aide pour l'éclaircir est la bienvenue.

Le serveur:

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"); 
     } 
    } 
} 

Le client:

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(); 
     } 
    } 
} 

Répondre

0

Vous ne pourrez pas voir la différence parce que readLine() attendra jusqu'à ce qu'un eol est lu. Pour voir la différence, utilisez des données binaires. Faire le flux sortant écrire des blocs de 64 octets séparés par 10ms dort. Rendre le flux entrant lire des blocs de 1024 octets. Lorsque tcpNoDelay est vrai, le flux entrant sera lu environ 64 octets à chaque opération de lecture. Lorsque tcpNoDelay est faux, le flux entrant lira beaucoup plus d'octets. Vous pouvez enregistrer le nombre moyen d'octets lus dans chaque opération de lecture, de sorte que la différence est évidente. Et testez toujours en utilisant deux machines, car le système d'exploitation peut optimiser les flux de bouclage.

+0

Vous pouvez tester avec un pair juste l'envoi et un autre juste la réception et la journalisation. Mais selon votre exemple, je comprends que vous voulez un voyage du serveur à des fins d'analyse comparative. Dans ce cas, laissez votre serveur avec tcpNoDelay toujours allumé et faites-lui lire un bloc de 4096 octets et répondez rapidement avec le nombre d'octets qu'il vient de lire. Vous verrez la différence en variant simplement tcpNoDelay sur le client. – fernacolo