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

多线程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();

请问如何区分用户输入的命令与客户端传输的文件内容?是否可以使用多组输入输出流?

解决方案
  • 通过协议约定区分内容类型
    给命令和文件内容添加明确的前缀标识:

    1. 命令传输前加前缀CMD:,监听线程读取到该前缀后解析为命令;
    2. 文件内容传输前加前缀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);
    
  • 使用独立的输入输出流
    完全可行,可拆分出两组独立流:

    1. 命令流:使用Socket默认的InputStream/OutputStream,仅用于传输命令;
    2. 文件数据流:在同一Socket连接上创建单独的DataInputStream/DataOutputStream,专门传输文件内容。
      这种方式能彻底避免命令与文件内容的读取混淆,监听线程和工作线程各用各的流,互不干扰。
  • 标记文件传输的边界
    放弃直接用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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.29 05:25:23