问题遇到的现象和发生背景
客户端使用protobuf协议,服务端用java接收的时候一直报Protocol message contained an invalid tag (zero).
问题相关代码,请勿粘贴截图
客户端的消息发送成功了
服务端报错内容
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需要一个自定义解码器
我想要达到的结果
不知道为什么,后端解码一直报错,有大佬能帮解答下吗?