Google协议缓冲区(Java到C++)
Google Protocol Buffer (Java to C++)
我正试图在Java和C++之间建立TCP/IP套接字连接,Java在Windows上,C++在Raspberry Pi上。正在传输的消息是一条谷歌协议缓冲区消息,其原型设置如下:
package package_name;
message Win2Pi{
optional int32 num1= 1;
optional int32 num2= 2;
optional int32 num3= 3;
optional int32 num4= 4;
optional bool logic1= 5;
optional bool logic2= 6;
optional bool logic3= 7;
optional bool logic4= 8;
optional bool logic5= 9;
optional int32 num5= 10;
optional bool logic6= 11;
}
我有以下Java(作为客户端(的代码:
/* Java Code to Open Socket, Create Protobuf Message, and Send */
Socket clientSocket = new Socket(hostName, portNumber);
BufferedReader in = new BufferedReader(new InputStreamReader(clientSocket.getInputStream()));
WinToPi.Builder w2p = WinToPi.newBuilder();
w2p.setNum1(255);
w2p.setNum2(255);
w2p.setNum3(255);
w2p.setNum4(255);
w2p.setLogic1(true);
w2p.setLogic2(true);
w2p.setLogic3(true);
w2p.setLogic4(true);
w2p.setLogic5(false);
w2p.setNum5(7);
w2p.setLogic6(true);
w2p.build().writeTo(clientSocket.getOutputStream());
我有以下C++(充当服务器(的代码:
//Protobuf Setup Variables
int sockfd, newsockfd, portno;
socklen_t clilen;
char buffer[1024];
struct sockaddr_in serv_addr, cli_addr;
int n;
sockfd = socket(AF_INET, SOCK_STREAM, 0);
if (sockfd < 0){
std::cout << "Error Opening Socket!" << std::endl;
exit(1); //error
}
bzero((char *) &serv_addr, sizeof(serv_addr));
portno = atoi(argv[1]);
serv_addr.sin_family = AF_INET;
serv_addr.sin_addr.s_addr = INADDR_ANY;
serv_addr.sin_port = htons(portno);
if (bind(sockfd, (struct sockaddr *) &serv_addr,sizeof(serv_addr)) < 0){
std::cout << "Error on Binding!" << std::endl; ;
exit(1); //error
}
listen(sockfd,5);
clilen = sizeof(cli_addr);
newsockfd = accept(sockfd, (struct sockaddr *) &cli_addr, &clilen);
if (newsockfd < 0) {
std::cout << "ERROR on accept" << std::endl;
exit(1);
}
/* Clear Buffer and Read Message from Client */
bzero(buffer,1024);
n = read(newsockfd,buffer,1023);
std::cout << "n: " << n << std::endl;
if (n < 0){
std::cout << "Error Reading From Socket!" << std::endl;
}
/* Translate Shoreside to Pi Message */
std::string inputStr = std::string(buffer);
package_name::WinToPi w2p;
w2p.ParseFromString(inputStr);
使用静态消息,我能够接收适当数量的字节和值。有了这一点,我开始让Java端的值动态变化。然而,在c++方面,我似乎会收到正确数量的字节,但大多数变量(只有前几个(的值不会改变。当我在Java端检查打包并传输的GoogleProtocol Buffer消息时,似乎我正在发送正确的值。有没有更好的方法可以在c++中接收Google Protocol Buffer消息?
您最大的问题似乎是:
std::string inputStr = std::string(buffer);
当您从const char*
构造这样的string
时,它将查找第一个NUL作为终止符。您应该使用。。。
std::string inputStr = std::string(buffer, n);
这将确保接收到的数据的整个块被存储到字符串中。
另一个问题:
套接字上的
read
可能会返回通过多个调用发送的任何内容,因此您应该始终采用一种约定来确定何时停止读取(例如,客户端和发送方已知的固定字节数-可能来自结构大小,或哨兵字符或序列,如换行符或NUL,或固定长度前缀(- 这是对流进行缓冲的自然结果:假设您的客户端应用程序在操作系统太忙而无法将任何数据真正放入网络数据包时调用
write
/send
三次:当它这样做时,它可能能够将前半秒的"写入"放入一个数据包,然后将第二秒的剩余部分与第三秒一起发送到另一个数据中;如果接收器期望每个read
读取一个多字节逻辑消息的开头,那么他们就会受到冲击
- 这是对流进行缓冲的自然结果:假设您的客户端应用程序在操作系统太忙而无法将任何数据真正放入网络数据包时调用
至于更好的方法,对于一些小规模的随意使用,我发现boost::asio
可以生成非常简洁、清晰的代码,使用它是一种乐趣。。。很多在线文档、示例、教程。
相关文章:
- 在java中解决这段代码时面临循环中的问题
- 尝试用java代码编译和运行c++代码
- 在这种情况下,java对象是否可以调用本机函数
- 在java中读取c++字节的位字段
- 为什么C++对链表中的下一个节点使用指针,而像 C# 或 Java 这样的语言只使用类 Node 的名称?
- 使用已使用 java 编码的 openssl 解码数据
- SWIG Java 在使用 -DSWIGWORDSIZE64 时将int64_t转换为 jlong
- Android Java USB for native cpp
- 在由Sublime文本3编译后在cmd上显示Java程序输出
- C++ equivalent to Java Map getOrDefault?
- C++ 中的 Java 样式枚举
- 是否有技术原因阻止 Java 中的 final C++ 像 const 一样严格?
- 加密在 Windows、C++ 和 Java 中传输中的数据
- Java从C++回调到C++回调
- 在 c++ 中模拟输入并在 JAVA 中读取它?
- 用C++包装 Java 库 (JNI)
- 使用 TreeSet Java 对反转进行计数
- 验证openssl c++中的签名,这是由JAVA DSA签名的?
- 如何通过 JNI 将 C 字符串表情符号传递给 Java
- 如何从保存在 Java 中C++的字节数组中读取数字?