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

Java Socket无法向Kotlin客户端返回错误消息的问题求助

问题描述
  • 已实现功能:
    • Kotlin客户端通过按钮发送消息至Java Socket服务端
    • Java服务端接收并分析客户端消息
  • 未实现功能:
    • Java服务端无法将消息语法错误信息以字符串形式返回给Kotlin客户端
    • Kotlin客户端无法接收该错误信息并保存至XML文件

Java Socket服务端原始代码

public static void main(String[] args) throws IOException, JSONException {
    sjf.setVisible(true);

    logger.info("Starting server...");
    sjf.agregarLog("Iniciando servidor");

    ServerSocket serverSocket = new ServerSocket(8080);
    logger.info("Server started on port {}", serverSocket.getLocalPort());

    while (true) {
        Socket clientSocket = serverSocket.accept();
        logger.info("Accepted connection from {}", clientSocket.getInetAddress().getHostAddress());
        sjf.agregarLog("Se acepto conexion");

        BufferedReader reader = new BufferedReader(new InputStreamReader(clientSocket.getInputStream()));

        StringBuilder messageBuilder = new StringBuilder(); 
        String line;
        while ((line = reader.readLine()) != null) { 
            messageBuilder.append(line);
            messageBuilder.append("\n"); 
        }
        String message = messageBuilder.toString(); 

        logger.info("Received message from {}: {}", clientSocket.getInetAddress().getHostAddress(), message);
        peti = message;
        sjf.agregarLog(peti);

        // write json file
        FileWriter fileWriter = new FileWriter(
                "mypath/archivo.json");

        fileWriter.write(message);
        fileWriter.close();
        // analizar
        aux = false;
        lista = new Lista(); // reiniciar lista de errores
        analizarMensaje();

//send errors feedback !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
OutputStream outputStream = socket.getOutputStream();
        PrintWriter printWriter = new PrintWriter(outputStream, true);
        printWriter.println("Hello, Kotlin!");
        printWriter.close();

    }
}

Kotlin客户端原始代码

private inner class SendMessageTask : AsyncTask<String, Void, Boolean>() {

    override fun doInBackground(vararg params: String): Boolean {
        try {
            val socket = Socket("192.168.0.36", 8080)
            val writer = PrintWriter(socket.getOutputStream(), true)
            for (mensaje in params) { 
                writer.println(mensaje) 
            }

            writer.close()
            

            // Receive the message from the Java socket and save it to a text file
            val inputStream = socket.getInputStream()
            val bufferedReader = BufferedReader(InputStreamReader(inputStream))
            val message = bufferedReader.readLine()
            bufferedReader.close()

            val file = File("received_message.txt")
            val printWriter = PrintWriter(file)
            printWriter.println(message)
            printWriter.close()

            println("Received message saved to file: ${file.absolutePath}")
            socket.close()
            return true
        } catch (e: Exception) {
            e.printStackTrace()
            return false
        }
    }

    override fun onPostExecute(result: Boolean) {
        if (!result) {
            Toast.makeText(context, "Error al enviar el mensaje", Toast.LENGTH_SHORT).show()
        }
    }
}

故障排查与修复方案

服务端问题修复

  1. 变量引用错误:发送反馈时误用未定义的socket变量,需替换为已建立连接的clientSocket
  2. 未返回实际错误信息:当前仅返回固定字符串,需替换为lista中存储的语法错误内容
  3. 流处理优化:确保输入流读取完成后再发送反馈,添加flush保证数据及时传输

修复后的服务端核心代码片段:

// ... 原有消息分析逻辑 ...

// 替换错误的发送反馈代码
OutputStream outputStream = clientSocket.getOutputStream();
PrintWriter printWriter = new PrintWriter(outputStream, true);
// 将lista中的错误转为字符串(根据你的Lista实现调整方法名)
String errorContent = lista.convertErrorsToString();
// 无错误时返回提示,否则返回错误信息
printWriter.println(errorContent.isEmpty() ? "无语法错误" : errorContent);
printWriter.flush();
printWriter.close();

// 最后关闭客户端socket
clientSocket.close();

客户端问题修复

  1. 过早关闭输出流:发送消息后立即关闭writer会导致socket流中断,需在接收完反馈后统一关闭socket
  2. XML格式保存:将原txt保存逻辑替换为XML格式生成
  3. 超时与异常优化:添加socket超时,避免无限等待,统一管理资源释放

修复后的客户端核心代码片段:

override fun doInBackground(vararg params: String): Boolean {
    var socket: Socket? = null
    try {
        socket = Socket("192.168.0.36", 8080)
        socket.soTimeout = 5000 // 设置5秒超时

        val writer = PrintWriter(socket.getOutputStream(), true)
        for (mensaje in params) {
            writer.println(mensaje)
        }
        writer.flush() // 刷新数据,不关闭流

        // 接收服务端反馈
        val bufferedReader = BufferedReader(InputStreamReader(socket.getInputStream()))
        val errorMsg = bufferedReader.readLine() ?: "未获取到错误信息"
        bufferedReader.close()

        // 生成XML内容并保存(保存到APP私有目录,无需额外权限)
        val xmlFile = File(context.getExternalFilesDir(null), "error_feedback.xml")
        val xmlContent = """<?xml version="1.0" encoding="UTF-8"?>
<errorFeedback>
    <errorMessage>$errorMsg</errorMessage>
</errorFeedback>""".trimIndent()
        
        val printWriter = PrintWriter(xmlFile)
        printWriter.println(xmlContent)
        printWriter.close()

        println("错误信息已保存至XML: ${xmlFile.absolutePath}")
        return true
    } catch (e: Exception) {
        e.printStackTrace()
        return false
    } finally {
        socket?.close() // 统一关闭socket
    }
}

额外注意事项

  • Android端若需保存到外部公共目录,需添加WRITE_EXTERNAL_STORAGE权限并在运行时申请
  • 服务端需确保Lista类实现convertErrorsToString()方法,遍历错误列表生成可读字符串
  • 建议服务端为每个客户端连接开启独立线程,避免单线程阻塞导致无法处理多连接

内容的提问来源于stack exchange,提问作者Ale

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.28 19:25:04