2015-11-03 186 views
1

我目前正在学习网络,特别是客户端 - 服务器类。 我已经做了大量的研究并实现了各种测试程序,但我无法弄清楚为什么/何时需要使用flush()方法。Java ObjectOutputStream的方法flush()

如果数据总是被输入流读入,怎么会有数据错误地留在输出流中呢?正如客户端 - 服务器代码所指示的那样。 我试图通过省略flush()来测试我的基本回显客户端服务器程序,但我无法打破它。

当通过从客户端写入两次并且只读取一次服务器的回复来测试flush()时,发生的所有事情都是服务器回复中的积压(我假设流类似于队列?)。 然后我采用了相同的代码,并在第二次写入之前和之后添加了flush(),并没有什么区别。就好像flush()并不真正清除流。

那么有人可以请解释什么情况下关于客户端/服务器流交互将冲洗()是必需的?

服务器:

public class ServerApp 
{ 
    private ServerSocket listener; 
    private Socket clientCon; 

    public ServerApp() 
    { 
     try 
     { 
      listener = new ServerSocket(1234, 10); 
     } catch (IOException e) 
     { 
      e.printStackTrace(); 
     } 
    } 

    public void listen() 
    { 
     try 
     { 
      System.out.println("Server is listening!"); 
      clientCon = listener.accept(); 
      System.out.println("Server: Connection made with Client"); 

      processClient(); 
     } catch (IOException e) 
     { 
      e.printStackTrace(); 
     } 
    } 

    public void processClient() 
    { 
     try(ObjectOutputStream out = new ObjectOutputStream(clientCon.getOutputStream()); ObjectInputStream in = new ObjectInputStream(clientCon.getInputStream())) 
     { 
      String msg; 
      while(!(msg = (String)in.readObject()).equalsIgnoreCase("Shutdown")) 
      { 
       out.writeObject("Server: " + msg); 
       out.flush(); 
      } 
      out.writeObject("Server is powering down..."); 

      out.close(); 
      in.close(); 
     } catch (IOException | ClassNotFoundException e) 
     { 
      e.printStackTrace(); 
     } 
    } 

    public static void main (String args[]) 
    { 
     ServerApp sa = new ServerApp(); 
     sa.listen(); 
    } 
} 

客户:

public class ClientApp 
{ 
    private Socket serverCon; 

    public ClientApp() 
    { 
     try 
     { 
      serverCon = new Socket("127.0.0.1", 1234); 
     } catch (IOException e) 
     { 
      e.printStackTrace(); 
     } 
    } 

    public void communicate() 
    { 
     try (ObjectOutputStream out = new ObjectOutputStream(serverCon.getOutputStream()); ObjectInputStream in = new ObjectInputStream(serverCon.getInputStream()); 
      BufferedReader br = new BufferedReader(new InputStreamReader(System.in))) 
     { 
      String response = null; 
      do 
      { 
       System.out.println("Enter your message for server: "); 
       out.writeObject(br.readLine()); 

       out.flush(); 
       out.writeObject("Flush not working"); 
       out.flush(); 

       response = (String) in.readObject(); 
       System.out.println(response); 

       response = (String) in.readObject(); 
       System.out.println(response); 
      } while (!response.equalsIgnoreCase("Server is powering down...")); 
     } catch (IOException | ClassNotFoundException e) 
     { 
      e.printStackTrace(); 
     } 
    } 

    public static void main(String args[]) 
    { 
     ClientApp ca = new ClientApp(); 
     ca.communicate(); 
    } 
} 

回答

2

方法flush()用于冲洗出了可用于使用任何内部缓冲器。例如,使用BufferedOutputStream将内容写入块以提高性能(写入每个字节的速度会比较慢)。

根据使用情况,您可能不必调用flush()。然而,假设您发送一个小的String(转换为byte[]),并且它很好地适合于内部缓冲区。在缓冲区已满或调用flush()之前,缓冲区的内容不会被发送。

现在假设您正在通过网络进行写作,并且您希望对方回答您的小问题String。由于它仍然在缓冲区中,对方将不会收到它,并可能导致双方永远等待。

对象流是另一个野兽,我有点失望,很多初学者都在使用它们。班上应该有一个警告,说“对象可能比他们看起来更难发送/接收”。

ObjectOutputStream委托flush()呼叫到其内部BlockDataOutputStream已3个缓冲器为“BLOCKDATA”,报头数据和字符尺寸分别10245256

0

尝试使用new ObjectOutputStream(new BufferedOutputStream(clientCon.getOutputStream())),您将看到有和没有的差异flush().它会导致底层缓冲输出流的刷新。如果没有缓冲流,则没有缓冲区来刷新,因此它什么都不做。

+0

奇怪的是,当我尝试在ServerApp中使用新的ObjectOutputStream(新的BufferedOutputStream(clientCon.getOutputStream()))时,ClientApp挂起(等待输入并且不输出“输入服务器消息”)。我应该采取的消息形式是,除非使用Buffered流,否则不需要使用flush()? – Shaun

相关问题