【问题标题】:How to properly parse JSON objects in a Java+C++ TCP connection?如何正确解析 Java+C++ TCP 连接中的 JSON 对象?
【发布时间】:2018-01-23 17:05:45
【问题描述】:

所以我想在 Java 客户端和 C++ 服务器之间建立 TCP 连接。将客户端视为输入设备,C++ 服务器应该接收 JSON 对象,解析它们并在游戏中使用它们。 似乎连接已成功建立,但是 1)当我尝试解析 json 对象(我正在使用nlohmann's json)时出现错误(“解析错误 - 意外''”)和 2)当我不'甚至调用 doStuff 也就是打印缓冲区,只打印奇怪的字符(例如)。

我假设我在发送/接收数据时搞砸了(这是我第一次使用 C++),但我已经失去了两天,真的想不通!

在我的 Java 客户端中:

private void connect() {
    try {
        hostname = conn.getHostname();
        portnumber = conn.getPortNr();
        socket = new Socket(hostname, portnumber);
        out = new OutputStreamWriter(socket.getOutputStream());
        in = new BufferedReader(new InputStreamReader(socket.getInputStream()));
    } catch (Exception e) {
        e.printStackTrace();
        Log.e(debugString, e.getMessage());
    }
}

public void sendMessage(String json) {
    try {
        //connect();
        out.write(json.length());
        Log.d(debugString, String.valueOf(json.length()));
        out.flush();
        out.write(json);
        out.flush();
        Log.d(debugString, json);

        in.read();
        this.close();
    } catch (Exception e) {
        e.printStackTrace();
        Log.e(debugString, e.getMessage());
    }
}

在 C++ 服务器中:

void Server::startConnection() {

  if (listen(s, 1) != 0) {
      perror("Error on listen");
      exit(EXIT_FAILURE);
  }

  listen(s, 1);

  clilen = sizeof(cli_addr);

  newsockfd = accept(s, (struct sockaddr *) &cli_addr, &clilen);
  if (newsockfd < 0) {
      close(newsockfd);
      perror("Server: ERROR on accept");
      exit(EXIT_FAILURE);
  }
  puts("Connection accepted");

    int numbytes;
    char buffer[MAXDATASIZE];
    while (1)
    {
        numbytes = recv(s,buffer,MAXDATASIZE-1,0);
        buffer[numbytes]='\0';
        //Here's where the weird stuff happens
        //cout << buffer;
        //doStuff(numbytes,buffer);

        if (numbytes==0)
        {
            cout << "Connection closed"<< endl;

            break;
        }
    }
}

bool Server::sendData(char *msg) {

    int len = strlen(msg);
    int bytes_sent = send(s,msg,len,0);
    if (bytes_sent == 0) {
        return false;
    } else {
        return true;
    }
}

void Server::doStuff(int numbytes, char * buf) {
    json jdata;
    try {
      jdata.clear();
      jdata = nlohmann::json::parse(buf);
      if (jdata["type"] == "life") {
        life = jdata["value"];
        puts("json parsed");
      }

    } catch (const std::exception& e) {
      cerr << "Unable to parse json: " << e.what() << std::endl;
    }
}

【问题讨论】:

  • 如果出现解析错误异常,那么您的数据可能包含一些意外字符。你能转储 buf 的内容并验证它是正确的 JSON 吗?

标签: java c++ json tcp nlohmann-json


【解决方案1】:

由于您的字符“缓冲区”在 C++ 服务器上的 recv() 之后显示奇怪的字符,因此在我看来,问题应该是由于 Java 客户端和 C++ 服务器之间的字符编码不匹配。为了验证您可以在 C++ 服务器上检查 recv() 返回的“numbytes”,它应该大于 Java 客户端上 JSON 字符串中的字符数。

【讨论】:

    【解决方案2】:

    您正在发送 JSON 长度的低 8 个字节,但您从未在接收器处对其进行任何处理。无论如何,这几乎肯定是一个错误。您不需要发送长度。 JSON 是自描述的。

    【讨论】:

    • 自我描述是什么意思?服务器只知道它正在接收字符,这些字符稍后会被解析为 json。
    • 它们应该现在被解析为 JSON。 “自我描述”是错误的,自我描述。但如果你需要长度字,你就需要它,而不仅仅是低 8 位,而且你需要在另一端使用它,而不是抱怨二进制打印为二进制。跨度>
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2013-10-14
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2017-10-31
    相关资源
    最近更新 更多