2016-11-15 1 views
2

Ich habe zwei Java-Klassen, einer ist der Server und der andere ist der Client. Angenommen, ich müsste 100 MB Daten vom Server zum Client senden. Wenn ich diese Nachricht sende, wartet der Server, bis der Client liest? Wenn Sie sich den Code ansehen, nimmt die EndTime-Variable des Servers keinen Wert an, bis der Client die 100 MB gelesen hat?Wenn Server Socket schreibt, wartet es, bis Client Socket liest?

Server-Klasse:

public class MyServerSocket { 

    private ServerSocket providerSocket; 
    private Socket connection = null; 
    private ObjectOutputStream out; 
    private ObjectInputStream in; 
    private String message; 

    public static void main(String[] args) {  
    MyServerSocket m = new MyServerSocket (); 
    m.establishConnection(); 
    } 

    public void establishConnection(){ 
     //SETUP CONNECTION 
     providerSocket = new ServerSocket(2004, 10); 
     connection = providerSocket.accept(); 
     out = new ObjectOutputStream(connection.getOutputStream()); 
     out.flush(); 
     in = new ObjectInputStream(connectiongetInputStream()); 
     //END SETUP CONNECTION 

     //Suppose this String contains 100 MB 
     String x = "Send 100MB of data"; 

     sendMessage("Server sends string x"); 

     //Here is the doubt 
     String startTime = System.nanotime(); 
     sendMessage(x); 
     String endTime = System.nanotime(); 

     do{ 
      message = (String)in.readObject();       

      if (message.contains("bye")){ 
       System.out.println("Server receives bye from Client"); 
      } 
     }while(!message.contains("bye"));   

    } 

    public void sendMessage(String msg) 
    { 
    try{ 
     out.writeObject(msg); 
     out.flush();   
    } 
    catch(IOException ioException){ 
      ioException.printStackTrace(); 
    } 
    } 
} 

Kunde Classs:

public class MyClientSocket { 

    private Socket requestSocket; 
    private ObjectInputStream in; 
    private ObjectOutputStream out; 
    private String message; 

    public static void main(String[] args) {  
     MyClientSocket n = new MyClientSocket(); 
     n.establishConnection(); 
    } 

    public void establishConnection(){ 
     requestSocket = new Socket("localhost", 2004); 
     in = new ObjectInputStream(requestSocket.getInputStream());         
     out = new ObjectOutputStream(requestSocket.getOutputStream()); 

     do{ 
      if(message instanceof String){ 
       message = (String)in.readObject();       
      }else{ 
       message = ""; 
      }      
      if(message.contains("Server sends string x")){ 
       //The following line reads the 100 MB String     
       String x = (String)in.readObject(); 

       sendMessage("bye");    
      }    
     }while(!message.contains("bye")); 
    } 

    public void sendMessage(String msg) 
    { 
    try{ 
     out.writeObject(msg); 
     out.flush();   
    } 
    catch(IOException ioException){ 
      ioException.printStackTrace(); 
    } 
    } 

Vielen Dank im Voraus

Antwort

0

Als ich diese Nachricht senden wird der Server wartet, bis der Client liest?

Steckdosen sind asynchron. Der Writer wartet nur auf freien Speicherplatz im Sendepuffer. Dieser Puffer ist jedoch begrenzt, oft um 64 KB. Wenn Sie eine große Datenmenge senden, muss der Absender auf Speicherplatz im Sendepuffer warten, bevor er weitere Daten schreiben kann.

Kurz gesagt, wenn der Empfänger schnell genug lesen kann, muss der Sender nie darauf warten. Wenn die Daten nicht schnell genug gesendet oder schnell genug gelesen werden können, füllt sich der Puffer und der Sender muss warten, bis mehr Platz ist.

Nimmt die endTime-Variable des Servers nicht Wert, bis der Client die 100 MB liest?

Die Endzeit ist nach dem letzten Stück Daten gesendet. Dies kann eine beliebige Zeitspanne sein, bis die Daten empfangen werden, höchstwahrscheinlich wird es jedoch keinen großen Unterschied machen, da die Datei viel größer als der Puffer ist. Für kleine Dateien ist es ziemlich bedeutungslos.

Die einzige Möglichkeit zu wissen, dass die Daten empfangen wurden, besteht darin, dass das andere Ende eine Nachricht zurücksendet, die besagt, dass die gesamte Datei empfangen wurde.

BTW Objekt-Streams sind eine großartige Möglichkeit, um jedes Objekt zu senden, jedoch ist es eines der langsamsten. Wenn Sie Benchmark sind, würde ich in Betracht ziehen, fast alles andere zu verwenden. (Verwenden Sie XMLEncoder ist schlechter) Verwenden Sie einen Datenstrom oder einen PrintWriter/BufferedReader.

+1

'Normalerweise nicht' sollte 'nie' sein. Jedes Mal, wenn der Schreibvorgang blockiert werden muss, liegt etwas über dem Sendepuffer, der gesendet werden muss. Es blockiert, während das, was bereits in dem Sendepuffer ist, gesendet und ACK'd ist, aber wenn das letzte Bit in den Sendepuffer kopiert wurde, kehrt es ohne weiteres zurück. – EJP

1

ServerSocketnicht schreiben. Socket schreibt. Das bedeutet nur, dass die Daten in den Socket-Sendepuffer des Kernels übertragen werden. Es besteht keine Implikation, dass die Daten gesendet, geschweige denn bestätigt, geschweige denn von der Peer-Anwendung gelesen wurden. Wenn Sie wissen müssen, dass Sie ACKs in Ihrem Anwendungsprotokoll benötigen.

+0

Bitte erklären Sie, für mein Verständnis, wenn Sie an die EndTime-Linie kommen, wurden in diesem Moment alle Daten gesendet? – Larx