我有一个多线程客户端-服务器系统,它来回工作,客户端首先通信,服务器回复。
但是,对于两个特定的客户端,我需要他们在用户进行输入时不断检查输入流中是否有数据,然后再继续。
该程序是一个 parking 场管理系统。当 parking 场已满(0 个可用车位)并且汽车到达入口客户端时,系统会形成等待准许进入的客户端队列。当汽车离开 parking 场时,队列中的第一个客户端将被删除并添加到该特定入口客户端的 BlockingQueue 中。我为每个入口客户端创建了一个直接输出输出流。因此,当 BlockingQueue 不为空时,将从该队列中获取数据并将输出发送到该特定客户端的流。
但是,问题是 - 排队的入口客户端应该自动读取其 InputStream 并打印数据以授予访问权限,但却导致错误并崩溃。我认为发生的情况是,当系统第一次启动时,客户端被困在等待读取最初不存在的数据,因为它在第一阶段需要某种输入,从而导致错误。
如何解决此问题,以便客户端读取并打印输入流(无论是特定数据,例如包含单词“队列”),如果有可用数据,则如果用户进行输入,则可以继续。
我希望这是有道理的,我尽力让它尽可能清楚。
服务器类别:
public class Server {
public static void main(String[] args) throws IOException {
//Create the shared objects in the global scope...
int groundFloor = 0; //SET TO 0 FOR TESTING
int firstFloor = 0;
SharedState SharedStateObject = new SharedState(groundFloor,firstFloor);
//Sets up the server socket on port 4444
ServerSocket serverSocket = null;
try
{
serverSocket = new ServerSocket(4444);
System.out.println("Car Park Server started." + "\n");
}
catch (IOException e) {
System.err.println("Could not start server on specified port.");
System.exit(-1);
}
//Got to do this in the correct order with only four clients!
ServerThread GroundFloorEntrance = new ServerThread(serverSocket.accept(), "GroundFloorEntrance", SharedStateObject);
ServerThread FirstFloorEntrance = new ServerThread(serverSocket.accept(), "FirstFloorEntrance", SharedStateObject);
ServerThread GroundFloorExit1 = new ServerThread(serverSocket.accept(), "GroundFloorExit1", SharedStateObject);
ServerThread GroundFloorExit2 = new ServerThread(serverSocket.accept(), "GroundFloorExit2", SharedStateObject);
GroundFloorEntrance.start();
FirstFloorEntrance.start();
GroundFloorExit1.start();
GroundFloorExit2.start();
serverSocket.close();
//Loop for granting queued clients access
while(true)
{
BlockingQueue<String> queuedGroundAccess = SharedStateObject.getQueuedGround();
BlockingQueue<String> queuedFirstAccess = SharedStateObject.getQueuedFirst();
if(!queuedGroundAccess.isEmpty())
{
Socket clientSocket = GroundFloorEntrance.clientSocket();
PrintWriter out = new PrintWriter(clientSocket.getOutputStream(), true);
try
{
out.println(queuedGroundAccess.take());
} catch (InterruptedException e) {
e.printStackTrace();
}
}
if(!queuedFirstAccess.isEmpty())
{
Socket clientSocket = FirstFloorEntrance.clientSocket();
PrintWriter out = new PrintWriter(clientSocket.getOutputStream(), true);
try
{
out.println(queuedFirstAccess.take());
} catch (InterruptedException e)
{
e.printStackTrace();
}
}
}
}
}
客户端
public class GroundFloorEntrance {
@SuppressWarnings("resource")
public static void main(String[] args) throws IOException {
// Set up the socket, in and out variables
Socket clientSocket = null;
PrintWriter out = null;
BufferedReader in = null;
int port = 4444;
String serverName = "localhost";
String clientID = "Ground Floor Entrance";
try {
clientSocket = new Socket(serverName, port);
out = new PrintWriter(clientSocket.getOutputStream(), true);
in = new BufferedReader(new InputStreamReader(clientSocket.getInputStream()));
} catch (UnknownHostException e) {
System.err.println("Don't know about host: " + serverName);
System.exit(1);
} catch (IOException e) {
System.err.println("Couldn't get I/O for the connection to: "+ port);
System.exit(1);
}
BufferedReader stdIn = new BufferedReader(new InputStreamReader(System.in));
String fromServer = null;
String fromUser = null;
System.out.println("Initialised " + clientID + " client and IO connections");
//I THINK THE ISSUE IN THE FOLLOWING STRUCTURE:
while (true) {
fromServer = in.readLine();
if(fromServer != null && fromServer.contains("Queue: "))
{
System.out.println(fromServer);
}
fromUser = stdIn.readLine();
if (fromUser != null) {
out.println(fromUser);
}
fromServer = in.readLine();
System.out.println(fromServer);
}
}
}
最佳答案
此循环中存在问题。当您编写 fromServer = in.readLine();
时,它会停止执行程序并等待从服务器输入数据。
while (true) {
fromServer = in.readLine();
if(fromServer != null && fromServer.contains("Queue: "))
{
System.out.println(fromServer);
}
fromUser = stdIn.readLine();
if (fromUser != null) {
out.println(fromUser);
}
fromServer = in.readLine();
System.out.println(fromServer);
}
你能用它做什么?您应该在另一个线程中从服务器读取数据,以防止在等待数据时阻塞主线程。像这样:
new Thread(new MyRunnable(fromServer)).start();
MyRunnable 将如下所示:
public class MyRunnable implements Runnable {
private Scanner scanner;
public MyRunnable(Scanner scanner) {
this.scanner = scanner;
}
@Override
public void run() {
while (true) {
if (scanner.hasNextLine()) {
System.out.println(scanner.nextLine());
}
}
}
}
如果您有任何疑问,请询问。
关于Java - 如何循环读取InputStream,直到用户输入继续?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/47580073/