C++与Java Socket通信使用Protobuf

C++与Java Socket通信使用Protobuf,第1张

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;
    }

    ...
}

希望对你们有用^_^

欢迎分享,转载请注明来源:内存溢出

原文地址: https://outofmemory.cn/langs/584965.html

(0)
打赏 微信扫一扫 微信扫一扫 支付宝扫一扫 支付宝扫一扫
上一篇 2022-04-12
下一篇 2022-04-12

发表评论

登录后才能评论

评论列表(0条)