Protobuf: Protobuf-3.6.1,内容是CMake、vs2017编译后的使用protobuf所需要的lib与protoc.exe,有Debug和Release版本,可以直接使用不用编译了。
也包含需要到的头文件
我把要用的东西都放在gitee里了,不知道你们能不能用。
我C++只学到了stl水平,windows mfc的没学,讲的不对的话见谅。
Java用的Netty
例子:
一、写个message.proto的文件
syntax = "proto2";
package com.li.cppserver; //java: com.li.cppserver.Message.CppMessage
//package Msg; //c++: Msg::CppMessage
message CppMessage
{
required int32 action = 1;
optional string username = 2;
optional string password = 3;
optional bool success = 4;
optional bytes content = 5;
}
数据类型对照:
C++给Java发还涉及编码的问题,所以我的content使用了bytes,java生成的.java文件中提供了转码的函数,使用方便多了。
二、在protoc.exe同级目录下执行cmd命令
C++:
protoc.exe --cpp_out=./ message.proto
Java:
protoc.exe --java_out=./ message.proto
C++的会生成两个文件:message.pb.cc和message.pb.h,我们直接复制到工程的头文件目录下。
Java的直接复制到对应package下,然后引入依赖:
com.google.protobuf
protobuf-java
3.6.1
三、修改项目配置
需要分别配置Release和Debug
相同配置:
1、项目 - 属性 - 常规,我的配置如图。
2、项目 - 属性 - C/C++ - 常规,在“附加包含目录”中添加包含所需头文件的文件夹的路径,就是我仓库里src的路径,你也可以下载官方的,就是图中的这个文件夹。
不同配置:
项目 - 属性 - 链接器 - 常规 - 附加库目录中 添加lib所在文件夹的路径,Release配置Release的,Debug配Debug的。
四、代码中的使用
C++:就酱紫蟀,基本的set,取success属性的时候是message.success()。
他这个message需要parse一下,我就不多说了,可以上网搜。
Msg::CppMessage SocketManager::receive(char * outBuf, int len){
Msg::CppMessage message;
message.set_success(false);
try{
int charCount;
if (socket == INVALID_SOCKET || socket == SOCKET_ERROR)
return message;
charCount = recv(socket, outBuf, len, 0);
if( charCount != SOCKET_ERROR && charCount > 0) {
outBuf[charCount] = '\0';
} else {
return message;
}
string receiveStr(outBuf, charCount + 1);
message.ParseFromString(receiveStr);
return message;
}catch(ConnException e){
cout<<"error in receive.."<
Java:非常简单,Encoder是我写的,Decoder是用的netty中的
//ProtobufEncoder
public class ProtobufEncoder extends MessageToByteEncoder {
@Override
protected void encode(ChannelHandlerContext channelHandlerContext, Message.CppMessage message, ByteBuf out) throws Exception {
byte[] bytes = message.toByteArray();
out.writeBytes(bytes);
}
}
//Initializer
@Override
protected void initChannel(SocketChannel channel) {
ChannelPipeline pipeline = channel.pipeline();
pipeline.addLast("decoder", new ProtobufDecoder(Message.CppMessage.getDefaultInstance()));
pipeline.addLast(new ProtobufEncoder());
pipeline.addLast(new IdleStateHandler(60, 70, 80));
pipeline.addLast(serverHandler);
}
//Handler
@Slf4j
@Component
@ChannelHandler.Sharable
public class CppServerHandler extends ChannelInboundHandlerAdapter {
@Override
public void channelRead(ChannelHandlerContext ctx, Object msg) throws Exception {
Message.CppMessage message = (Message.CppMessage) msg;
NioSocketChannel channel = (NioSocketChannel) ctx.channel();
String id = (String) channel.attr(AttributeKey.valueOf("id")).get();
log.info("接收到消息{}", message.info());
switch (message.getAction()) {
case 0:
this.register(channel, message);
break;
case 1:
sendMessage(id, message);
break;
case 2:
Message.CppMessage.Builder builder = Message.CppMessage.newBuilder()
.setAction(1)
.setSuccess(true)
.setContent(encode("[INFO] 服务器获取到心跳"));
ctx.writeAndFlush(builder.build());
break;
}
}
private ByteString encode(String content) {
try {
return ByteString.copyFrom(content, "GBK");
} catch (UnsupportedEncodingException e) {
e.printStackTrace();
}
return null;
}
...
}
希望对你们有用^_^
欢迎分享,转载请注明来源:内存溢出
评论列表(0条)