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"。
ObjectOutputStream
将 flush()
调用委托给其内部 BlockDataOutputStream
,它有 3 个大小为 1024
、5
和 256
的缓冲区 "blockdata",头数据和字符分别。
使用 new ObjectOutputStream(new BufferedOutputStream(clientCon.getOutputStream()))
尝试一下,您会发现使用和不使用 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"。
ObjectOutputStream
将 flush()
调用委托给其内部 BlockDataOutputStream
,它有 3 个大小为 1024
、5
和 256
的缓冲区 "blockdata",头数据和字符分别。
使用 new ObjectOutputStream(new BufferedOutputStream(clientCon.getOutputStream()))
尝试一下,您会发现使用和不使用 flush().
的区别。它会导致底层缓冲输出流的刷新。没有缓冲流就没有要刷新的缓冲区,所以它什么都不做。