多线程FTP服务器客户端:如何区分命令与文件传输数据流?
问题描述
我正尝试开发一款支持后台任务的多线程服务器客户端FTP,允许客户端在后台执行put等任务(如put test.txt),同时可输入新命令。目前已实现用于客户端Socket连接的监听线程,以及处理get/put命令的工作线程(仅这两个命令需后台运行)。
当前遇到的问题是:执行put等后台任务时,监听线程会读取客户端发送的文件内容,并将其误认为新命令,从而抛出NumberFormatException异常。
监听线程代码:
try { command = input.readUTF(); String[] splitCommand = command.split("\\s+"); String fileName = ""; if (splitCommand.length > 1) fileName = splitCommand[1]; executeCommand(Integer.valueOf(splitCommand[0]), fileName); } catch (IOException i) { System.out.println(i); System.exit(0); }
工作线程代码:
File file = new File(currDirectory + fileName); file.createNewFile(); String data = ""; data = input.readUTF(); fileWriter = new FileWriter(currDirectory + fileName); fileWriter.write(data); fileWriter.close();
请问如何区分用户输入的命令与客户端传输的文件内容?是否可以使用多组输入输出流?
解决方案
通过协议约定区分内容类型
给命令和文件内容添加明确的前缀标识:- 命令传输前加前缀
CMD:,监听线程读取到该前缀后解析为命令; - 文件内容传输前加前缀
DATA:,工作线程识别后处理文件数据。
调整监听线程逻辑:
try { String content = input.readUTF(); if (content.startsWith("CMD:")) { String command = content.substring(4); String[] splitCommand = command.split("\\s+"); String fileName = ""; if (splitCommand.length > 1) fileName = splitCommand[1]; executeCommand(Integer.valueOf(splitCommand[0]), fileName); } } catch (IOException i) { System.out.println(i); System.exit(0); }客户端发送文件前先写入标识:
output.writeUTF("DATA:"); output.writeUTF(fileContent);- 命令传输前加前缀
使用独立的输入输出流
完全可行,可拆分出两组独立流:- 命令流:使用Socket默认的
InputStream/OutputStream,仅用于传输命令; - 文件数据流:在同一Socket连接上创建单独的
DataInputStream/DataOutputStream,专门传输文件内容。
这种方式能彻底避免命令与文件内容的读取混淆,监听线程和工作线程各用各的流,互不干扰。
- 命令流:使用Socket默认的
标记文件传输的边界
放弃直接用readUTF()读取文件内容,改为先传输文件长度,再传输字节数据:
工作线程调整代码:File file = new File(currDirectory + fileName); file.createNewFile(); int fileLength = input.readInt(); byte[] fileBytes = new byte[fileLength]; input.readFully(fileBytes); FileOutputStream fos = new FileOutputStream(file); fos.write(fileBytes); fos.close();客户端对应逻辑:
byte[] fileBytes = Files.readAllBytes(Paths.get("test.txt")); output.writeInt(fileBytes.length); output.write(fileBytes);这种方式通过长度值明确划分文件内容的边界,监听线程只会处理固定格式的命令,不会误读文件数据。
内容的提问来源于stack exchange,提问作者Diana
相关产品推荐
相关产品推荐

