2014-06-28 52 views
0

因此,這裏是我的代碼:在服務器刷新數據之前,數據如何由服務器的套接字接收?

public class TestClass { 
    public static void main(String[] args) throws IOException, InterruptedException { 
     Thread server = new Thread(new MyServer()); 
     server.start(); 
     Thread.sleep(750); 
     Thread client = new Thread(new MyClient()); 
     client.start(); 
    } 
} 

服務器:

public class MyServer implements Runnable{ 

    public static synchronized void go() throws IOException { 

     System.out.println("MyServer: Go called..."); 
     ServerSocket serverSocket = new ServerSocket(5000); 
     while(true){ 
      Socket socket = serverSocket.accept(); 
      System.out.println(time() + "MyServer: Connection accepted!"); 
      OutputStream outputStream = socket.getOutputStream(); 
      System.out.println(time() + "MyServer: socket.getOutputStream"); 
      PrintWriter printWriter = new PrintWriter(outputStream); 
      System.out.println(time() + "MyServer: New PrintWriter object created!"); 
      printWriter.write("Hello from my socket!"); 
      System.out.println(time() + "MyServer: printwriter.write method called.."); 
      printWriter.flush(); 
      System.out.println(time() + "MyServer: Flushed!"); 
      printWriter.close(); 
      System.out.println(time() + "MyServer: printWriter closed..."); 
     } 
    } 

    public static String time(){ 
     return String.valueOf(MyCounterClass.getCounter()) + " "; 
    } 

    @Override 
    public void run() { 
     try { 
      go(); 
     } catch (IOException e) { 
      e.printStackTrace(); 
     } 
    } 
} 

客戶:

public class MyClient implements Runnable { 

    public static synchronized void go() throws IOException { 
     Socket socket = new Socket("localhost",5000); 
     System.out.println(time() + "My Client: Connection established..."); 
     InputStream inputStream = socket.getInputStream(); 
     System.out.println(time() + "MyClient: socket.getInputStream..."); 
     BufferedReader bufferedReader = new BufferedReader(new InputStreamReader(inputStream)); 
     System.out.println(time() + "MyClient: BufferedReader object created..."); 
     System.out.println(time() + "Bufferedreader readline being called and directly printer: " + bufferedReader.readLine()); 
     System.out.println(time() + "bufferedReader.readline has just been called..."); 
    } 

    public static String time(){ 
     return String.valueOf(MyCounterClass.getCounter()) + " "; 
    } 

    @Override 
    public void run() { 
     try { 
      go(); 
     } catch (IOException e) { 
      e.printStackTrace(); 
     } 
    } 

}

和反類:

public class MyCounterClass { 
    private static volatile int counter = 0; 
    synchronized public static int getCounter(){ 
     return counter++; 
    } 
} 

和輸出將是:

0 My Client: Connection established... 
1 MyServer: Connection accepted! 
2 MyClient: socket.getInputStream... 
3 MyClient: BufferedReader object created... 
4 MyServer: socket.getOutputStream 
6 MyServer: New PrintWriter object created! 
7 MyServer: printwriter.write method called.. 
8 MyServer: Flushed! 
9 MyServer: printWriter closed... 
5 Bufferedreader readline being called and directly printer: Hello from my socket! 
10 bufferedReader.readline has just been called... 

當下令:

0 My Client: Connection established... 
1 MyServer: Connection accepted! 
2 MyClient: socket.getInputStream... 
3 MyClient: BufferedReader object created... 
4 MyServer: socket.getOutputStream 
5 Bufferedreader readline being called and directly printer: Hello from my socket! 
6 MyServer: New PrintWriter object created! 
7 MyServer: printwriter.write method called.. 
8 MyServer: Flushed! 
9 MyServer: printWriter closed... 
10 bufferedReader.readline has just been called... 

那麼,什麼是怪我是5號線是6,7,8 ......之前這是如何可能?

+1

「沖洗」意味着數據確保已傳輸,否則該方法將一直等待。它可以更快地傳遞。 –

+0

[爲什麼我在Socket連接中的Java線程中看到這種奇怪的輸出?](http://stackoverflow.com/questions/24468356/why-am-i-seeing-this-weird-output-in-java -threads-in-socket-connections) – alk

+0

@alk它不是重複的。 –

回答

3

有發生在這裏

System.out.println(time() + "Bufferedreader readline being called and directly printer: " + bufferedReader.readLine()); 

首先time()一些事情被調用來得到一個值。說它返回5.該值存儲在堆棧中。然後readLine()被調用並阻塞,直到它收到一些東西。一旦完成,它會連接來自堆棧的5,從readLine返回的String"Bufferedreader read...「和String

因此,即使flush()(並寫入流)稍後,從time()的值已被檢索。

你需要圍繞整個String連接操作進行同步。

+0

當我將其更改爲... readLine()+時,一切都很酷,所以非常感謝。 –

1

flush將以編程方式清空併發送剩餘的緩衝區內容,但這並不意味着當緩衝區在通過套接字傳輸期間完全填滿時不會執行其他自動刷新。

也就是說,必須使用flush以確保當您完成傳輸時發送緩衝區中的最後一批數據。但是,填充 - 發送 - 刷新的許多迭代可能同時發生。

enter image description here

在此圖中,你go方法中進行明確flush是一個負責發送紅色字節。

它可能發生,您的緩衝區永遠不會調用之前填充flush,在這種情況下,直到調用完成客戶端將不被髮送的字節數:

enter image description here

編輯雖然在這個答案中暴露的是正確的,但它不是對你遇到的問題的完整解釋,Sotirios的回答增加了對你的代碼的其他問題的更多見解。不要忘記,在go結束時的沖刷並不意味着在那一刻發送完整的塊,m * sizeof(buffer)可能在此之前已經被髮送。

+0

我不明白這與問題有關。在6,7,8之前5是如何發生的?你的答案如何解釋? –

+0

@SotiriosDelimanolis「在服務器刷新數據之前,服務器上的套接字如何接收數據」儘管我的回答並未攻擊所有情況,但它解決了爲什麼5在8之前可能發生。 –

+0

對於8發生,必須發生6和7發生了。在服務器創建發送數據的對象之前,客戶端無法收到數據。這裏的問題是日誌記錄是誤導性的。 –

相關問題