2016-11-15 3 views
2

私は2つのJavaクラスを持っています.1つはサーバーで、もう1つはクライアントです。サーバーからクライアントに100MBのデータを送信する必要があるとします。このメッセージを送信すると、サーバーはクライアントが読み取るまで待機しますか? コードを見ると、クライアントの100 MBが読み取られるまで、ServerのendTime変数は値を取得しませんか?サーバソケット書き込み時、クライアントソケットが読み込まれるまで待機しますか?

Serverクラス:

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

クライアント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(); 
    } 
    } 

おかげ

答えて

0

私はクライアントが読み込むまで、このメッセージは、サーバが待機しない送りますか?

ソケットは非同期です。ライターは、送信バッファ内の空き領域だけを待ちます。ただし、このバッファには制限があり、多くの場合約64 KBです。大量のデータを送信する場合、送信側は送信バッファ内のスペースを待たなくてはなりません。

つまり、受信者が十分に速く読むことができれば、送信者はそれを待つ必要はありません。データを十分に速く送ることができないか、または十分に速く読むことができない場合は、バッファがいっぱいになり、送信者はスペースがなくなるまで待たなければなりません。

クライアントの100 MBが読み取られるまで、ServerのendTime変数は値を取りませんか?

endTimeは最後のデータが送信された後です。これは、データが受信されるまでの任意の時間である可能性がありますが、ファイルがバッファよりもはるかに大きいのでほとんど違いはありません。小さなファイルの場合、それはかなり無意味です。

データを受信したことを知る唯一の方法は、相手側がファイル全体を受信したというメッセージを返すことです。

BTWオブジェクトストリームはオブジェクトを送信するための優れた方法ですが、最も遅い方法の1つです。あなたがベンチマークであれば、私は他の何かを使うことを検討します。 (XMLEncoderの使用は悪いです)データストリームまたはPrintWriter/BufferedReaderを試してみてください。

+1

'通常はありません'は '決して'ではありません。書き込みをブロックする必要があるときはいつも、送信バッファの上に何かがあるためです。それは送信バッファ内の何が送信され、ACKされているかをブロックしますが、最後のビットが送信バッファにコピーされると、それはそれ以上の煩わしさを伴わずに戻ります。 – EJP

1

ServerSocketを書いてください。 Socketと書いています。これは、データがカーネルのソケット送信バッファに転送されることを意味します。ピアアプリケーションによって読み取られるのではなく、データが送信されていることは何の意味もありません。アプリケーションプロトコルで何らかのACKが必要であることを知る必要がある場合。

+0

endTimeラインに到達したときの私の理解のために、この時点ですべてのデータが送信されたことを説明してください。 – Larx

関連する問題