首页 > 解决方案 > 从 Java 客户端发送的命令在被 C++ 服务器端接收之前被分割成多个部分

问题描述

我正在尝试通过 TCP 连接从我的客户端(使用 Java 实现)发送命令到使用 C++ 实现的服务器端。服务器端代码已经给出并经过测试,所以我相当肯定命令的解析不是问题。但是当我尝试从 Java 端发送字符串命令时,服务器端有时会收到多个包,因此无法正确解析。由于服务器仅在命令以换行符结尾时才执行命令,因此命令的第一部分被丢弃并引发未知消息错误。我在 Java 端使用 DataOutputStream,并使用 DataOutputStream.writeBytes(String s) 编写命令,并使用 BufferedReader 读取服务器返回的消息。

我可以通过使用 telnet 连接到服务器而不启动 Java 端代码来测试服务器。从 telnet,我可以成功发送多个命令并且它们被正确解析。但是,当我尝试从 Java 发送命令时,它们会被分解成碎片。第一个命令总是很好,它总是“add_server 3\n”,第二个命令“dec_dimmer\n”被分成“d”和“ec_dimmer\n”,所有后续命令都以类似的方式时尚。

以下是发送命令部分的实现方式:

DataOutputStream outToServer = null;
        try {
            outToServer = new DataOutputStream(mClientSocket.getOutputStream());
        } catch(IOException e) {
            e.printStackTrace();
        }

        try {
            String cmd = command + '\n';
            if(mDebug) {
                System.out.println("Sending Command: " + cmd);
            }
            outToServer.writeBytes(cmd);
        } catch (IOException e) {
            e.printStackTrace();
        }
BufferedReader inFromServer = null;
        try {
            inFromServer = new BufferedReader(new InputStreamReader(mClientSocket.getInputStream()));
        } catch(IOException e) {
            e.printStackTrace();
        }


        String jsonOutput = null;
        try {
            jsonOutput = inFromServer.readLine();
        } catch(IOException e) {
            e.printStackTrace();
        }

        if(mDebug) {
            System.out.println("FROM SERVER: " + jsonOutput);
        }

        return jsonOutput;

此外,完全相同的客户端之前已经在 c++ 中实现过,并且运行良好。以下函数是c++版本客户端的发送命令函数:

std::string SwimClient::sendCommand(const char* command) {
    if (!socket.is_open()) {
        throw std::runtime_error("socket is closed");
    }

    boost::system::error_code ignored_error;
    cout << "sending command = " << command << endl;
    boost::asio::write(socket, boost::asio::buffer(command, strlen(command)),
              boost::asio::transfer_all(), ignored_error);


    vector<char> buffer(128);
    boost::system::error_code error;

    size_t len = socket.read_some(boost::asio::buffer(buffer), error);

    if (error)
        throw boost::system::system_error(error);

    string reply(buffer.data(), len);
    if (reply.compare(0, 6, "error:") == 0) {
        // trim strings
        size_t last = reply.length() - 1;
        while (isspace(reply.at(last))) {
            reply.erase(last--);
        }
        string cmd(command);
        last = cmd.length() - 1;
        while (isspace(cmd.at(last))) {
            cmd.erase(last--);
        }

        throw std::logic_error(reply + "(cmd " + cmd + ')');
    }

    return reply;
}

标签: javac++tcpdataoutputstream

解决方案


推荐阅读