Java Socket通信:for循环第二次迭代卡住问题求助
问题描述
我正在实现服务端-客户端消息交互功能:先询问客户端要执行的任务数量,再通过for循环依次获取每个任务的描述和状态,创建Tarea类对象并存入ArrayList。但执行到第二次迭代时控制台挂起,无法进行后续迭代,推测状态获取环节也存在相同问题。以下是我编写的代码,恳请帮助,谢谢。
原代码
Server.java
package server; import java.io.DataInputStream; import java.io.DataOutputStream; import java.io.IOException; import java.net.ServerSocket; import java.net.Socket; import java.util.ArrayList; import java.util.Scanner; public class Server { private final int Port = 9876; private ServerSocket serverSocket; private Socket socket; ArrayList<Tarea> tarea = new ArrayList<Tarea>(); Scanner sc = new Scanner(System.in); public Server() throws IOException { serverSocket = new ServerSocket(Port); socket = new Socket(); } public void iniciarServidor() throws IOException { while (true) { System.out.println("Esperando al cliente"); socket = serverSocket.accept(); System.out.println("El cliente se ha conectado"); DataOutputStream input = new DataOutputStream(socket.getOutputStream()); DataInputStream output = new DataInputStream(socket.getInputStream()); input.writeUTF("Introduzca el nombre del cliente: "); String nombre = output.readUTF(); System.out.println("Nombre cliente: " + nombre); String descripcion = ""; boolean estado; Tarea t = new Tarea(); input.writeUTF("Muy buenas " + nombre + " especifique numero de tareas:"); int numeroTareas = output.readInt(); for(int i = 0;i<numeroTareas;i++){ input.writeUTF("Especifique descripcion para la tarea "+i+" :"); descripcion = output.readUTF(); input.writeUTF("Especifique el estado 'true o false' para la tarea "+i+" :"); estado = output.readBoolean(); t = new Tarea(descripcion,estado); tarea.add(t); } sc.nextLine(); input.writeUTF("El servidor va a enviar todas las tareas"); for(int i = 0;i<tarea.size();i++){ input.writeUTF("Numero tarea: "+i); input.writeUTF("Descripcion: "+tarea.get(i).getDescripcion()); input.writeUTF("Estado: "+tarea.get(i).isEstado()); } socket.close(); System.out.println("Cliente desconectado"); output.close(); input.close(); } } }
Client.java
package client; import java.io.DataInputStream; import java.io.DataOutputStream; import java.io.IOException; import java.net.Socket; import java.util.ArrayList; import java.util.Scanner; import server.Tarea; public class Client { private final String Host = "localhost"; private final int Port = 9876; private final Socket socket; ArrayList<Tarea> tarea = new ArrayList<Tarea>(); public Client() throws IOException { socket = new Socket(Host, Port); } public void iniciarCliente() throws IOException { String descripcion; boolean estado; DataInputStream input = new DataInputStream(socket.getInputStream()); DataOutputStream output = new DataOutputStream(socket.getOutputStream()); Scanner sc = new Scanner(System.in); //Servidor solicita nombre usuario System.out.println(input.readUTF()); output.writeUTF(sc.nextLine()); //Numero de tareas a realizar System.out.println(input.readUTF()); int numeroTareas = sc.nextInt(); output.writeInt(numeroTareas); sc.nextLine(); //Servidor solicita descripcion tarea System.out.println(input.readUTF()); descripcion = sc.next(); output.writeUTF(descripcion); //Servidor solicita estado de tarea System.out.println(input.readUTF()); estado = sc.nextBoolean(); output.writeBoolean(estado); //Servidor confirma que va a enviar las tareas System.out.println(input.readUTF()); //Servidor envia todas las tareas; System.out.println(input.readUTF()); System.out.println(input.readUTF()); System.out.println(input.readUTF()); socket.close(); input.close(); output.close(); System.out.println("Fin, Desconectado del servidor"); sc.close(); } }
Tarea.java
package server; import java.util.ArrayList; /** * * @author Lluis */ public class Tarea { private String descripcion; private boolean estado; public Tarea(){ } public Tarea(String descripcion, boolean estado){ this.descripcion = descripcion; this.estado = estado; } public String mandarDesc(ArrayList<Tarea> tarea) { for(int i=0; i<tarea.size(); i++) { setDescripcion(tarea.get(i).getDescripcion()); } return getDescripcion(); } public boolean mandarEstado(ArrayList<Tarea> tarea) { for(int i=0; i<tarea.size(); i++) { setEstado(tarea.get(i).isEstado()); } return isEstado(); } public String toString() { return getDescripcion()+ " Estado: /n " + isEstado(); } /** * @return the descripcion */ public String getDescripcion() { return descripcion; } /** * @param descripcion the descripcion to set */ public void setDescripcion(String descripcion) { this.descripcion = descripcion; } /** * @return the estado */ public boolean isEstado() { return estado; } /** * @param estado the estado to set */ public void setEstado(boolean estado) { this.estado = estado; } }
问题分析与修复方案
核心问题
- 客户端未循环处理多任务:原客户端代码仅处理了1次任务的描述和状态输入,当服务端循环请求第2个及以后的任务数据时,客户端没有响应,导致服务端阻塞等待。
- 服务端多余的控制台读取:服务端中的
sc.nextLine()完全多余,会导致服务端卡在等待控制台输入的步骤,无法继续执行。 - 客户端读取返回数据逻辑固定:原客户端只固定读取3条服务端返回的信息,但实际任务数量是动态的,会出现读取不匹配的问题。
修复后的代码
Server.java(修复后)
package server; import java.io.DataInputStream; import java.io.DataOutputStream; import java.io.IOException; import java.net.ServerSocket; import java.net.Socket; import java.util.ArrayList; public class Server { private final int Port = 9876; private ServerSocket serverSocket; private Socket socket; ArrayList<Tarea> tarea = new ArrayList<Tarea>(); public Server() throws IOException { serverSocket = new ServerSocket(Port); socket = new Socket(); } public void iniciarServidor() throws IOException { while (true) { System.out.println("Esperando al cliente"); socket = serverSocket.accept(); System.out.println("El cliente se ha conectado"); DataOutputStream outputToClient = new DataOutputStream(socket.getOutputStream()); DataInputStream inputFromClient = new DataInputStream(socket.getInputStream()); outputToClient.writeUTF("Introduzca el nombre del cliente: "); String nombre = inputFromClient.readUTF(); System.out.println("Nombre cliente: " + nombre); String descripcion = ""; boolean estado; outputToClient.writeUTF("Muy buenas " + nombre + " especifique numero de tareas:"); int numeroTareas = inputFromClient.readInt(); // 清空之前的任务列表,避免连接复用导致数据残留 tarea.clear(); for(int i = 0;i<numeroTareas;i++){ outputToClient.writeUTF("Especifique descripcion para la tarea "+i+" :"); descripcion = inputFromClient.readUTF(); outputToClient.writeUTF("Especifique el estado 'true o false' para la tarea "+i+" :"); estado = inputFromClient.readBoolean(); Tarea t = new Tarea(descripcion,estado); tarea.add(t); } outputToClient.writeUTF("El servidor va a enviar todas las tareas"); for(int i = 0;i<tarea.size();i++){ outputToClient.writeUTF("Numero tarea: "+i); outputToClient.writeUTF("Descripcion: "+tarea.get(i).getDescripcion()); outputToClient.writeUTF("Estado: "+tarea.get(i).isEstado()); } // 先关闭流再关闭socket inputFromClient.close(); outputToClient.close(); socket.close(); System.out.println("Cliente desconectado"); } } }
Client.java(修复后)
package client; import java.io.DataInputStream; import java.io.DataOutputStream; import java.io.IOException; import java.net.Socket; import java.util.Scanner; public class Client { private final String Host = "localhost"; private final int Port = 9876; private final Socket socket; public Client() throws IOException { socket = new Socket(Host, Port); } public void iniciarCliente() throws IOException { DataInputStream inputFromServer = new DataInputStream(socket.getInputStream()); DataOutputStream outputToServer = new DataOutputStream(socket.getOutputStream()); Scanner sc = new Scanner(System.in); // 处理用户名输入 System.out.println(inputFromServer.readUTF()); outputToServer.writeUTF(sc.nextLine()); // 处理任务数量输入 System.out.println(inputFromServer.readUTF()); int numeroTareas = sc.nextInt(); outputToServer.writeInt(numeroTareas); sc.nextLine(); // 循环处理每个任务的描述和状态 for(int i = 0; i < numeroTareas; i++){ System.out.println(inputFromServer.readUTF()); String descripcion = sc.nextLine(); outputToServer.writeUTF(descripcion); System.out.println(inputFromServer.readUTF()); boolean estado = sc.nextBoolean(); outputToServer.writeBoolean(estado); sc.nextLine(); // 读取换行符,避免影响下一次输入 } // 接收服务端的提示信息 System.out.println(inputFromServer.readUTF()); // 循环读取所有任务的返回信息 for(int i = 0; i < numeroTareas; i++){ System.out.println(inputFromServer.readUTF()); System.out.println(inputFromServer.readUTF()); System.out.println(inputFromServer.readUTF()); } // 关闭资源 inputFromServer.close(); outputToServer.close(); socket.close(); System.out.println("Fin, Desconectado del servidor"); sc.close(); } }
Tarea.java(优化后)
原代码中的mandarDesc和mandarEstado方法逻辑错误,每次循环会覆盖当前对象的属性,仅返回最后一个任务的数据,且这些方法实际未被使用,建议删除:
package server; /** * * @author Lluis */ public class Tarea { private String descripcion; private boolean estado; public Tarea(){ } public Tarea(String descripcion, boolean estado){ this.descripcion = descripcion; this.estado = estado; } @Override public String toString() { return descripcion + " Estado: \n " + estado; } public String getDescripcion() { return descripcion; } public void setDescripcion(String descripcion) { this.descripcion = descripcion; } public boolean isEstado() { return estado; } public void setEstado(boolean estado) { this.estado = estado; } }
内容的提问来源于stack exchange,提问作者Louis98
相关产品推荐
相关产品推荐

