我目前正在学习网络,特别是客户端 - 服务器类。 我做了很多研究并实现了各种测试程序,但我无法弄清楚为什么/何时需要使用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();
}
}
答案 0 :(得分:2)
方法flush()
用于清除可能正在使用的任何内部缓冲区。例如,使用BufferedOutputStream
内容以块的形式写入以提高性能(在每个字节到来时写入速度会慢一些。)
根据使用情况,您可能永远不必调用flush()。但是,我们假设您发送一个小的String
(转换为byte[]
),它很适合内部缓冲区。在缓冲区已满或调用flush()
之前,缓冲区的内容不会被发送。
现在让我们说你正在通过网络写作,而你希望对方能够回答你的小String
。由于它还在缓冲区中,另一方不会收到它,这可能导致双方永远等待。
对象流是另一种野兽,我对有这么多初学者使用它们感到有点失望。在课堂上应该有一个警告说"对象可能比它们出现的更难发送/接收"。
ObjectOutputStream
委托flush()
调用其内部BlockDataOutputStream
,其中有3个缓冲区,大小为1024
,5
和256
用于&#34 ; blockdata",分别为标题数据和字符。
答案 1 :(得分:0)
尝试使用new ObjectOutputStream(new BufferedOutputStream(clientCon.getOutputStream()))
,您会看到有和没有flush().
的区别它会导致刷新底层缓冲输出流。如果没有缓冲流,则没有缓冲区可以刷新,因此它什么都不做。