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() } } }
故障排查与修复方案
服务端问题修复
- 变量引用错误:发送反馈时误用未定义的
socket变量,需替换为已建立连接的clientSocket - 未返回实际错误信息:当前仅返回固定字符串,需替换为
lista中存储的语法错误内容 - 流处理优化:确保输入流读取完成后再发送反馈,添加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();
客户端问题修复
- 过早关闭输出流:发送消息后立即关闭
writer会导致socket流中断,需在接收完反馈后统一关闭socket - XML格式保存:将原txt保存逻辑替换为XML格式生成
- 超时与异常优化:添加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
相关产品推荐
相关产品推荐

