客户端使用protobuf协议,服务端用java接收的时候一直报Protocol message contained an invalid tag (zero).

问题遇到的现象和发生背景

客户端使用protobuf协议,服务端用java接收的时候一直报Protocol message contained an invalid tag (zero).

问题相关代码,请勿粘贴截图

客户端的消息发送成功了

img

服务端报错内容

img

io.netty.handler.codec.DecoderException: com.google.protobuf.InvalidProtocolBufferException: Protocol message contained an invalid tag (zero).
at io.netty.handler.codec.MessageToMessageDecoder.channelRead(MessageToMessageDecoder.java:98)
at io.netty.channel.AbstractChannelHandlerContext.invokeChannelRead(AbstractChannelHandlerContext.java:379)
at io.netty.channel.AbstractChannelHandlerContext.invokeChannelRead(AbstractChannelHandlerContext.java:365)
at io.netty.channel.AbstractChannelHandlerContext.fireChannelRead(AbstractChannelHandlerContext.java:357)
at io.netty.handler.codec.ByteToMessageDecoder.fireChannelRead(ByteToMessageDecoder.java:324)
at io.netty.handler.codec.ByteToMessageDecoder.fireChannelRead(ByteToMessageDecoder.java:311)
at io.netty.handler.codec.ByteToMessageDecoder.callDecode(ByteToMessageDecoder.java:425)
at io.netty.handler.codec.ByteToMessageDecoder.channelRead(ByteToMessageDecoder.java:276)
at io.netty.channel.AbstractChannelHandlerContext.invokeChannelRead(AbstractChannelHandlerContext.java:379)
at io.netty.channel.AbstractChannelHandlerContext.invokeChannelRead(AbstractChannelHandlerContext.java:365)
at io.netty.channel.AbstractChannelHandlerContext.fireChannelRead(AbstractChannelHandlerContext.java:357)
at io.netty.channel.DefaultChannelPipeline$HeadContext.channelRead(DefaultChannelPipeline.java:1410)
at io.netty.channel.AbstractChannelHandlerContext.invokeChannelRead(AbstractChannelHandlerContext.java:379)
at io.netty.channel.AbstractChannelHandlerContext.invokeChannelRead(AbstractChannelHandlerContext.java:365)
at io.netty.channel.DefaultChannelPipeline.fireChannelRead(DefaultChannelPipeline.java:919)
at io.netty.channel.nio.AbstractNioByteChannel$NioByteUnsafe.read(AbstractNioByteChannel.java:166)
at io.netty.channel.nio.NioEventLoop.processSelectedKey(NioEventLoop.java:719)
at io.netty.channel.nio.NioEventLoop.processSelectedKeysOptimized(NioEventLoop.java:655)
at io.netty.channel.nio.NioEventLoop.processSelectedKeys(NioEventLoop.java:581)
at io.netty.channel.nio.NioEventLoop.run(NioEventLoop.java:493)
at io.netty.util.concurrent.SingleThreadEventExecutor$4.run(SingleThreadEventExecutor.java:989)
at io.netty.util.internal.ThreadExecutorMap$2.run(ThreadExecutorMap.java:74)
at io.netty.util.concurrent.FastThreadLocalRunnable.run(FastThreadLocalRunnable.java:30)
at java.lang.Thread.run(Thread.java:748)
Caused by: com.google.protobuf.InvalidProtocolBufferException: Protocol message contained an invalid tag (zero).
at com.google.protobuf.InvalidProtocolBufferException.invalidTag(InvalidProtocolBufferException.java:133)
at com.google.protobuf.CodedInputStream$ArrayDecoder.readTag(CodedInputStream.java:633)
at com.ma.mhxy.protobuf.Message$NetMessage.(Message.java:298)
at com.ma.mhxy.protobuf.Message$NetMessage.(Message.java:261)
at com.ma.mhxy.protobuf.Message$NetMessage$1.parsePartialFrom(Message.java:1030)
at com.ma.mhxy.protobuf.Message$NetMessage$1.parsePartialFrom(Message.java:1024)
at com.google.protobuf.AbstractParser.parsePartialFrom(AbstractParser.java:158)
at com.google.protobuf.AbstractParser.parseFrom(AbstractParser.java:191)
at com.google.protobuf.AbstractParser.parseFrom(AbstractParser.java:197)
at com.google.protobuf.AbstractParser.parseFrom(AbstractParser.java:48)
at io.netty.handler.codec.protobuf.ProtobufDecoder.decode(ProtobufDecoder.java:119)
at io.netty.handler.codec.protobuf.ProtobufDecoder.decode(ProtobufDecoder.java:66)
at io.netty.handler.codec.MessageToMessageDecoder.channelRead(MessageToMessageDecoder.java:88)

C# 使用的Message的proto文件

syntax = "proto3";

package SkillBridge.Message;

option csharp_namespace = "SkillBridge.Message";

option cc_enable_arenas = true;

////////////////////////////////////////////////////////////////
//
// Basic Defines
//
////////////////////////////////////////////////////////////////
enum RESULT
{
SUCCESS = 0;
FAILED = 1;
}

enum CHARACTER_CLASS
{
NONE = 0;
}

////////////////////////////////////////////////////////////////
//
// Messages
//
////////////////////////////////////////////////////////////////

message NetMessage{
NetMessageRequest Request = 1;
NetMessageResponse Response = 2;
}

message NetMessageRequest{
UserRegisterRequest userRegister = 1;
UserLoginRequest userLogin = 2;
UserCreateCharacterRequest createChar = 3;

}

message NetMessageResponse{
UserRegisterResponse userRegister = 1;
UserLoginResponse userLogin = 2;
UserCreateCharacterResponse createChar = 3;

}

// User Protocol
message UserLoginRequest {
string user = 1;
string passward = 2;
}

message UserLoginResponse {
RESULT result = 1;
string errormsg = 2;
NUserInfo userinfo = 3;
}

message UserRegisterRequest
{
string user = 1;
string passward = 2;
}

message UserRegisterResponse {
RESULT result = 1;
string errormsg = 2;
}

message UserCreateCharacterRequest
{
string name = 1;
CHARACTER_CLASS class = 2;
}

message UserCreateCharacterResponse {
RESULT result = 1;
string errormsg = 2;
repeated NCharacterInfo characters = 3;
}

message NUserInfo {
int32 id = 1;
NPlayerInfo player = 2;
}

message NPlayerInfo {
int32 id = 1;
repeated NCharacterInfo characters = 2;
}

message NCharacterInfo {
int32 id = 1;//db id
int32 config_id = 2;//config id
int32 entity_id = 3;//entity id
string name = 4;
int32 level = 7;
int32 mapId = 8;
int64 gold = 10;
int32 ride = 17;
}

message NEntity {
int32 id = 1;
NVector3 position = 2;
NVector3 direction = 3;
int32 speed = 4;
}

message NVector3
{
int32 x = 1;
int32 y = 2;
int32 z = 3;
}

java使用的proto文件__

// 声明使用proto3
syntax = "proto3";
// 包名
option java_package = "com.ma.mhxy.protobuf";
// 类名
option java_outer_classname = "Message";

enum RESULT
{
SUCCESS = 0;
FAILED = 1;
}

enum CHARACTER_CLASS
{
NONE = 0;
}

////////////////////////////////////////////////////////////////
//
// Messages
//
////////////////////////////////////////////////////////////////

message NetMessage{
NetMessageRequest Request = 1;
NetMessageResponse Response = 2;
}

message NetMessageRequest{
UserRegisterRequest userRegister = 1;
UserLoginRequest userLogin = 2;
UserCreateCharacterRequest createChar = 3;

}

message NetMessageResponse{
UserRegisterResponse userRegister = 1;
UserLoginResponse userLogin = 2;
UserCreateCharacterResponse createChar = 3;

}

// User Protocol
message UserLoginRequest {
string user = 1;
string passward = 2;
}

message UserLoginResponse {
RESULT result = 1;
string errormsg = 2;
NUserInfo userinfo = 3;
}

message UserRegisterRequest
{
string user = 1;
string passward = 2;
}

message UserRegisterResponse {
RESULT result = 1;
string errormsg = 2;
}

message UserCreateCharacterRequest
{
string name = 1;
CHARACTER_CLASS class = 2;
}

message UserCreateCharacterResponse {
RESULT result = 1;
string errormsg = 2;
repeated NCharacterInfo characters = 3;
}

message NUserInfo {
int32 id = 1;
NPlayerInfo player = 2;
}

message NPlayerInfo {
int32 id = 1;
repeated NCharacterInfo characters = 2;
}

message NCharacterInfo {
int32 id = 1;//db id
int32 config_id = 2;//config id
int32 entity_id = 3;//entity id
string name = 4;
int32 level = 7;
int32 mapId = 8;
int64 gold = 10;
int32 ride = 17;
}

message NEntity {
int32 id = 1;
NVector3 position = 2;
NVector3 direction = 3;
int32 speed = 4;
}

message NVector3
{
int32 x = 1;
int32 y = 2;
int32 z = 3;
}

这个是c#服务器的正常解析代码
///


/// 数据包解析
///

///
bool ParsePackage()
{
if (readOffset + 4 < stream.Position)
{
int packageSize = BitConverter.ToInt32(stream.GetBuffer(), readOffset);
if (packageSize + readOffset + 4 <= stream.Position)
{//包有效

                SkillBridge.Message.NetMessage message = UnpackMessage(stream.GetBuffer(), this.readOffset + 4, packageSize);
                if (message == null)
                {
                    throw new Exception("PackageHandler ParsePackage faild,invalid package");
                }
                MessageDistributer<T>.Instance.ReceiveMessage(this.sender, message);
                this.readOffset += (packageSize + 4);
                return ParsePackage();
            }
        }

        //未接收完/要结束了
        if (this.readOffset > 0)
        {
            long size = stream.Position - this.readOffset;
            if (this.readOffset < stream.Position)
            {
                Array.Copy(stream.GetBuffer(), this.readOffset, stream.GetBuffer(), 0, stream.Position - this.readOffset);
            }
            //Reset Stream
            this.readOffset = 0;
            stream.Position = size;
            stream.SetLength(size);
        }
        return true;
    }

是c#的解包的代码,c#这边是能正常收发数据,是不是java需要一个自定义解码器

我想要达到的结果

不知道为什么,后端解码一直报错,有大佬能帮解答下吗?

这个问题我之前碰到过,但是好久没用了,也忘记当时咋解决的了。https://stackoverflow.com/questions/19258313/protostuff-throws-protocol-message-contained-an-invalid-tag-zero# https://stackoverflow.com/questions/26598419/protocol-message-contained-an-invalid-tag-zero 你看看对你有没有帮助吧.

img


这个是c#的解包的代码,c#这边是能正常收发数据,是不是java需要一个自定义解码器

估计是你C#定义的消息类和java的有名称不匹配 ,仔细核对下