【问题标题】:Java ObjectOutputStream's Method flush()Java ObjectOutputStream 的方法 flush()
【发布时间】:2016-02-03 10:37:34
【问题描述】:

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

【问题讨论】:

    标签: java client-server flush objectoutputstream


    【解决方案1】:

    flush() 方法用于清除可能正在使用的任何内部缓冲区。例如使用BufferedOutputStream,内容被分块写入以提高性能(写入每个字节时会更慢)。

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

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

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

    ObjectOutputStreamflush() 调用委托给它的内部 BlockDataOutputStream,它有 3 个大小为 10245256 的缓冲区,分别用于“块数据”、标题数据和字符。

    【讨论】:

      【解决方案2】:

      new ObjectOutputStream(new BufferedOutputStream(clientCon.getOutputStream())) 试试,你会发现有和没有flush(). 的区别它会导致底层缓冲输出流的刷新。如果没有缓冲流,就没有要刷新的缓冲区,所以它什么也不做。

      【讨论】:

      • 奇怪的是,当我尝试在 ServerApp 中使用 new ObjectOutputStream(new BufferedOutputStream(clientCon.getOutputStream())) 时,ClientApp 挂起(等待输入并且不打印“输入服务器消息”)。除非使用缓冲流,否则我应该采取这种形式的消息是您不需要使用 flush() 吗?
      猜你喜欢
      • 2018-04-13
      • 1970-01-01
      • 1970-01-01
      • 2014-04-16
      • 2018-09-23
      • 2012-08-08
      • 1970-01-01
      • 2015-01-05
      • 1970-01-01
      相关资源
      最近更新 更多