You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

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. 客户端未循环处理多任务:原客户端代码仅处理了1次任务的描述和状态输入,当服务端循环请求第2个及以后的任务数据时,客户端没有响应,导致服务端阻塞等待。
  2. 服务端多余的控制台读取:服务端中的sc.nextLine()完全多余,会导致服务端卡在等待控制台输入的步骤,无法继续执行。
  3. 客户端读取返回数据逻辑固定:原客户端只固定读取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

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.10 06:35:26