2014-06-28 45 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发生了。在服务器创建发送数据的对象之前,客户端无法收到数据。这里的问题是日志记录是误导性的。 –

相关问题