Java ObjectOutputStream的方法flush()

时间:2015-11-03 10:10:01

标签: java client-server flush objectoutputstream

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

如果输入流始终读入数据,那么输出流中是否会错误地保留数据?由客户端 - 服务器代码决定。 我试图通过省略flush()来测试我的基本echo客户端服务器程序,但我无法破解它。

当通过从客户端写两次并且只读取一次服务器的回复来测试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 个答案:

答案 0 :(得分:2)

方法flush()用于清除可能正在使用的任何内部缓冲区。例如,使用BufferedOutputStream内容以块的形式写入以提高性能(在每个字节到来时写入速度会慢一些。)

根据使用情况,您可能永远不必调用flush()。但是,我们假设您发送一个小的String(转换为byte[]),它很适合内部缓冲区。在缓冲区已满或调用flush()之前,缓冲区的内容不会被发送。

现在让我们说你正在通过网络写作,而你希望对方能够回答你的小String。由于它还在缓冲区中,另一方不会收到它,这可能导致双方永远等待。

对象流是另一种野兽,我对有这么多初学者使用它们感到有点失望。在课堂上应该有一个警告说"对象可能比它们出现的更难发送/接收"。

ObjectOutputStream委托flush()调用其内部BlockDataOutputStream,其中有3个缓冲区,大小为10245256用于&#34 ; blockdata",分别为标题数据和字符。

答案 1 :(得分:0)

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