Java ObjectOutputStream 的方法 flush()

Java ObjectOutputStream's Method flush()

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

一直由输入流读入,怎么会有数据误留在输出流中?按照客户端-服务器代码的规定。 我试图通过省略 flush() 来测试我的基本 echo 客户端服务器程序,但我无法破坏它。

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

那么有人可以解释一下在什么情况下需要 flush() client/server 流交互吗?

服务器:

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();
    }
}

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

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

现在假设您正在通过网络写作,并且您希望对方对您的小 String 做出一些回答。由于它仍在缓冲区中,另一方不会收到它,这可能导致双方永远等待。

对象流是另一种野兽,令我有点失望的是有这么多初学者在使用它们。 class 中应该有一个警告说 "Objects may be more difficult to send/receive than they appear"。

ObjectOutputStreamflush() 调用委托给其内部 BlockDataOutputStream,它有 3 个大小为 10245256 的缓冲区 "blockdata",头数据和字符分别。

使用 new ObjectOutputStream(new BufferedOutputStream(clientCon.getOutputStream())) 尝试一下,您会发现使用和不使用 flush(). 的区别。它会导致底层缓冲输出流的刷新。没有缓冲流就没有要刷新的缓冲区,所以它什么都不做。