【MINA】用protobuf做编解码协议

SOCKET协议

支持java serial 与 AMF3的混合协议,目前没有基于xml 与 json的实现。

 

 协议说明:

* 9个字节协议头+协议体.
*
* 协议头1-4字节表示协议长度 =协议体长度+9-4(去掉长度占的4字节)
*
* 协议头第5字节为标志字节:
*------------------------
* 该字节的最低位为压缩位:0=协议体未压缩 1=协议体已经压缩,
* 该字节的低2-4位为协议位:
* 000=基于AMF3的协议,
* 001=基于java serial协议
* 010=基于protobuf协议
* 5-8位未用,作为以后扩展
* ------------------------
*
* 6-9字节表示命令号
*
* 采用网络字节序的整数(高位在前,低位在后)

 

                                                1-4协议长度                                6-9cmd

1

2

3

4

5

标志位

6

 

7

 

8

9

 数据(AMF3或者java serial

 

目前支持3种序列化协议。protobuf没有做额外的压缩,也没有做加密,但是将来都可以用标志位来做,这里另外两种不做解释,主要说protobuf

准备工作

protobuf-java-2.5.0.jar

自定义的proto文件ChatMsg.proto

protoc.exe编译工具

编译命令proto.bat

 

#ChatMsg.proto

package tutorial;

option java_package = "com.youxigu.dynasty2.chat.proto";
option java_outer_classname = "ChatMsg";

//异常请求
message BadRequest{
   required int32 cmd = 1;
   required int32 errCode = 2;
   required string err = 3;
}

//同步请求标志
message SyncStat{
   required int64 id = 1;
   required int32 stat = 2[default=1];
}

//10009 聊天请求
message ChatActionReceive{
   required int32 cmd = 1;
   required int32 errCode = 2;
   required string err = 3;
   optional int64 toUserId = 4;
   optional string toUserName = 5;
   required string channel = 6;
   required string context = 7;
   optional string channelId = 8;
}

//10010 聊天响应
message ChatActionReceiveReturn{
   required int32 cmd = 1;
   required int32 errCode = 2;
   required string err = 3;
   required int32 requestCmd = 4;
}
View Code

#proto.bat

cd E:\heart\workspace\dynasty2_mobile_new_v0.1\proto
E:
protoc.exe --java_out=./ ChatMsg.proto
View Code

编译万生成ChatMsg.jaba

// Generated by the protocol buffer compiler.  DO NOT EDIT!
// source: ChatMsg.proto

package com.youxigu.dynasty2.chat.proto;

public final class ChatMsg {
  private ChatMsg() {}
  public static void registerAllExtensions(
      com.google.protobuf.ExtensionRegistry registry) {
  }
  public interface BadRequestOrBuilder
      extends com.google.protobuf.MessageOrBuilder {

    // required int32 cmd = 1;
    /**
     * <code>required int32 cmd = 1;</code>
     */
    boolean hasCmd();
    /**
     * <code>required int32 cmd = 1;</code>
     */
    int getCmd();

    // required int32 errCode = 2;
    /**
     * <code>required int32 errCode = 2;</code>
     */
    boolean hasErrCode();
    /**
     * <code>required int32 errCode = 2;</code>
     */
    int getErrCode();

    // required string err = 3;
    /**
     * <code>required string err = 3;</code>
     */
    boolean hasErr();
    /**
     * <code>required string err = 3;</code>
     */
    java.lang.String getErr();
    /**
     * <code>required string err = 3;</code>
     */
    com.google.protobuf.ByteString
        getErrBytes();
  }
  /**
   * Protobuf type {@code tutorial.BadRequest}
   *
   * <pre>
   *异常请求
   * </pre>
   */
  public static final class BadRequest extends
      com.google.protobuf.GeneratedMessage
      implements BadRequestOrBuilder {
    // Use BadRequest.newBuilder() to construct.
    private BadRequest(com.google.protobuf.GeneratedMessage.Builder<?> builder) {
      super(builder);
      this.unknownFields = builder.getUnknownFields();
    }
    private BadRequest(boolean noInit) { this.unknownFields = com.google.protobuf.UnknownFieldSet.getDefaultInstance(); }

    private static final BadRequest defaultInstance;
    public static BadRequest getDefaultInstance() {
      return defaultInstance;
    }

    public BadRequest getDefaultInstanceForType() {
      return defaultInstance;
    }

    private final com.google.protobuf.UnknownFieldSet unknownFields;
    @java.lang.Override
    public final com.google.protobuf.UnknownFieldSet
        getUnknownFields() {
      return this.unknownFields;
    }
    private BadRequest(
        com.google.protobuf.CodedInputStream input,
        com.google.protobuf.ExtensionRegistryLite extensionRegistry)
        throws com.google.protobuf.InvalidProtocolBufferException {
      initFields();
      int mutable_bitField0_ = 0;
      com.google.protobuf.UnknownFieldSet.Builder unknownFields =
          com.google.protobuf.UnknownFieldSet.newBuilder();
      try {
        boolean done = false;
        while (!done) {
          int tag = input.readTag();
          switch (tag) {
            case 0:
              done = true;
              break;
            default: {
              if (!parseUnknownField(input, unknownFields,
                                     extensionRegistry, tag)) {
                done = true;
              }
              break;
            }
            case 8: {
              bitField0_ |= 0x00000001;
              cmd_ = input.readInt32();
              break;
            }
            case 16: {
              bitField0_ |= 0x00000002;
              errCode_ = input.readInt32();
              break;
            }
            case 26: {
              bitField0_ |= 0x00000004;
              err_ = input.readBytes();
              break;
            }
          }
        }
      } catch (com.google.protobuf.InvalidProtocolBufferException e) {
        throw e.setUnfinishedMessage(this);
      } catch (java.io.IOException e) {
        throw new com.google.protobuf.InvalidProtocolBufferException(
            e.getMessage()).setUnfinishedMessage(this);
      } finally {
        this.unknownFields = unknownFields.build();
        makeExtensionsImmutable();
      }
    }
    public static final com.google.protobuf.Descriptors.Descriptor
        getDescriptor() {
      return com.youxigu.dynasty2.chat.proto.ChatMsg.internal_static_tutorial_BadRequest_descriptor;
    }

    protected com.google.protobuf.GeneratedMessage.FieldAccessorTable
        internalGetFieldAccessorTable() {
      return com.youxigu.dynasty2.chat.proto.ChatMsg.internal_static_tutorial_BadRequest_fieldAccessorTable
          .ensureFieldAccessorsInitialized(
              com.youxigu.dynasty2.chat.proto.ChatMsg.BadRequest.class, com.youxigu.dynasty2.chat.proto.ChatMsg.BadRequest.Builder.class);
    }

    public static com.google.protobuf.Parser<BadRequest> PARSER =
        new com.google.protobuf.AbstractParser<BadRequest>() {
      public BadRequest parsePartialFrom(
          com.google.protobuf.CodedInputStream input,
          com.google.protobuf.ExtensionRegistryLite extensionRegistry)
          throws com.google.protobuf.InvalidProtocolBufferException {
        return new BadRequest(input, extensionRegistry);
      }
    };

    @java.lang.Override
    public com.google.protobuf.Parser<BadRequest> getParserForType() {
      return PARSER;
    }

    private int bitField0_;
    // required int32 cmd = 1;
    public static final int CMD_FIELD_NUMBER = 1;
    private int cmd_;
    /**
     * <code>required int32 cmd = 1;</code>
     */
    public boolean hasCmd() {
      return ((bitField0_ & 0x00000001) == 0x00000001);
    }
    /**
     * <code>required int32 cmd = 1;</code>
     */
    public int getCmd() {
      return cmd_;
    }

    // required int32 errCode = 2;
    public static final int ERRCODE_FIELD_NUMBER = 2;
    private int errCode_;
    /**
     * <code>required int32 errCode = 2;</code>
     */
    public boolean hasErrCode() {
      return ((bitField0_ & 0x00000002) == 0x00000002);
    }
    /**
     * <code>required int32 errCode = 2;</code>
     */
    public int getErrCode() {
      return errCode_;
    }

    // required string err = 3;
    public static final int ERR_FIELD_NUMBER = 3;
    private java.lang.Object err_;
    /**
     * <code>required string err = 3;</code>
     */
    public boolean hasErr() {
      return ((bitField0_ & 0x00000004) == 0x00000004);
    }
    /**
     * <code>required string err = 3;</code>
     */
    public java.lang.String getErr() {
      java.lang.Object ref = err_;
      if (ref instanceof java.lang.String) {
        return (java.lang.String) ref;
      } else {
        com.google.protobuf.ByteString bs = 
            (com.google.protobuf.ByteString) ref;
        java.lang.String s = bs.toStringUtf8();
        if (bs.isValidUtf8()) {
          err_ = s;
        }
        return s;
      }
    }
    /**
     * <code>required string err = 3;</code>
     */
    public com.google.protobuf.ByteString
        getErrBytes() {
      java.lang.Object ref = err_;
      if (ref instanceof java.lang.String) {
        com.google.protobuf.ByteString b = 
            com.google.protobuf.ByteString.copyFromUtf8(
                (java.lang.String) ref);
        err_ = b;
        return b;
      } else {
        return (com.google.protobuf.ByteString) ref;
      }
    }

    private void initFields() {
      cmd_ = 0;
      errCode_ = 0;
      err_ = "";
    }
    private byte memoizedIsInitialized = -1;
    public final boolean isInitialized() {
      byte isInitialized = memoizedIsInitialized;
      if (isInitialized != -1) return isInitialized == 1;

      if (!hasCmd()) {
        memoizedIsInitialized = 0;
        return false;
      }
      if (!hasErrCode()) {
        memoizedIsInitialized = 0;
        return false;
      }
      if (!hasErr()) {
        memoizedIsInitialized = 0;
        return false;
      }
      memoizedIsInitialized = 1;
      return true;
    }

    public void writeTo(com.google.protobuf.CodedOutputStream output)
                        throws java.io.IOException {
      getSerializedSize();
      if (((bitField0_ & 0x00000001) == 0x00000001)) {
        output.writeInt32(1, cmd_);
      }
      if (((bitField0_ & 0x00000002) == 0x00000002)) {
        output.writeInt32(2, errCode_);
      }
      if (((bitField0_ & 0x00000004) == 0x00000004)) {
        output.writeBytes(3, getErrBytes());
      }
      getUnknownFields().writeTo(output);
    }

    private int memoizedSerializedSize = -1;
    public int getSerializedSize() {
      int size = memoizedSerializedSize;
      if (size != -1) return size;

      size = 0;
      if (((bitField0_ & 0x00000001) == 0x00000001)) {
        size += com.google.protobuf.CodedOutputStream
          .computeInt32Size(1, cmd_);
      }
      if (((bitField0_ & 0x00000002) == 0x00000002)) {
        size += com.google.protobuf.CodedOutputStream
          .computeInt32Size(2, errCode_);
      }
      if (((bitField0_ & 0x00000004) == 0x00000004)) {
        size += com.google.protobuf.CodedOutputStream
          .computeBytesSize(3, getErrBytes());
      }
      size += getUnknownFields().getSerializedSize();
      memoizedSerializedSize = size;
      return size;
    }

    private static final long serialVersionUID = 0L;
    @java.lang.Override
    protected java.lang.Object writeReplace()
        throws java.io.ObjectStreamException {
      return super.writeReplace();
    }

    public static com.youxigu.dynasty2.chat.proto.ChatMsg.BadRequest parseFrom(
        com.google.protobuf.ByteString data)
        throws com.google.protobuf.InvalidProtocolBufferException {
      return PARSER.parseFrom(data);
    }
    public static com.youxigu.dynasty2.chat.proto.ChatMsg.BadRequest parseFrom(
        com.google.protobuf.ByteString data,
        com.google.protobuf.ExtensionRegistryLite extensionRegistry)
        throws com.google.protobuf.InvalidProtocolBufferException {
      return PARSER.parseFrom(data, extensionRegistry);
    }
    public static com.youxigu.dynasty2.chat.proto.ChatMsg.BadRequest parseFrom(byte[] data)
        throws com.google.protobuf.InvalidProtocolBufferException {
      return PARSER.parseFrom(data);
    }
    public static com.youxigu.dynasty2.chat.proto.ChatMsg.BadRequest parseFrom(
        byte[] data,
        com.google.protobuf.ExtensionRegistryLite extensionRegistry)
        throws com.google.protobuf.InvalidProtocolBufferException {
      return PARSER.parseFrom(data, extensionRegistry);
    }
    public static com.youxigu.dynasty2.chat.proto.ChatMsg.BadRequest parseFrom(java.io.InputStream input)
        throws java.io.IOException {
      return PARSER.parseFrom(input);
    }
    public static com.youxigu.dynasty2.chat.proto.ChatMsg.BadRequest parseFrom(
        java.io.InputStream input,
        com.google.protobuf.ExtensionRegistryLite extensionRegistry)
        throws java.io.IOException {
      return PARSER.parseFrom(input, extensionRegistry);
    }
    public static com.youxigu.dynasty2.chat.proto.ChatMsg.BadRequest parseDelimitedFrom(java.io.InputStream input)
        throws java.io.IOException {
      return PARSER.parseDelimitedFrom(input);
    }
    public static com.youxigu.dynasty2.chat.proto.ChatMsg.BadRequest parseDelimitedFrom(
        java.io.InputStream input,
        com.google.protobuf.ExtensionRegistryLite extensionRegistry)
        throws java.io.IOException {
      return PARSER.parseDelimitedFrom(input, extensionRegistry);
    }
    public static com.youxigu.dynasty2.chat.proto.ChatMsg.BadRequest parseFrom(
        com.google.protobuf.CodedInputStream input)
        throws java.io.IOException {
      return PARSER.parseFrom(input);
    }
    public static com.youxigu.dynasty2.chat.proto.ChatMsg.BadRequest parseFrom(
        com.google.protobuf.CodedInputStream input,
        com.google.protobuf.ExtensionRegistryLite extensionRegistry)
        throws java.io.IOException {
      return PARSER.parseFrom(input, extensionRegistry);
    }

    public static Builder newBuilder() { return Builder.create(); }
    public Builder newBuilderForType() { return newBuilder(); }
    public static Builder newBuilder(com.youxigu.dynasty2.chat.proto.ChatMsg.BadRequest prototype) {
      return newBuilder().mergeFrom(prototype);
    }
    public Builder toBuilder() { return newBuilder(this); }

    @java.lang.Override
    protected Builder newBuilderForType(
        com.google.protobuf.GeneratedMessage.BuilderParent parent) {
      Builder builder = new Builder(parent);
      return builder;
    }
    /**
     * Protobuf type {@code tutorial.BadRequest}
     *
     * <pre>
     *异常请求
     * </pre>
     */
    public static final class Builder extends
        com.google.protobuf.GeneratedMessage.Builder<Builder>
       implements com.youxigu.dynasty2.chat.proto.ChatMsg.BadRequestOrBuilder {
      public static final com.google.protobuf.Descriptors.Descriptor
          getDescriptor() {
        return com.youxigu.dynasty2.chat.proto.ChatMsg.internal_static_tutorial_BadRequest_descriptor;
      }

      protected com.google.protobuf.GeneratedMessage.FieldAccessorTable
          internalGetFieldAccessorTable() {
        return com.youxigu.dynasty2.chat.proto.ChatMsg.internal_static_tutorial_BadRequest_fieldAccessorTable
            .ensureFieldAccessorsInitialized(
                com.youxigu.dynasty2.chat.proto.ChatMsg.BadRequest.class, com.youxigu.dynasty2.chat.proto.ChatMsg.BadRequest.Builder.class);
      }

      // Construct using com.youxigu.dynasty2.chat.proto.ChatMsg.BadRequest.newBuilder()
      private Builder() {
        maybeForceBuilderInitialization();
      }

      private Builder(
          com.google.protobuf.GeneratedMessage.BuilderParent parent) {
        super(parent);
        maybeForceBuilderInitialization();
      }
      private void maybeForceBuilderInitialization() {
        if (com.google.protobuf.GeneratedMessage.alwaysUseFieldBuilders) {
        }
      }
      private static Builder create() {
        return new Builder();
      }

      public Builder clear() {
        super.clear();
        cmd_ = 0;
        bitField0_ = (bitField0_ & ~0x00000001);
        errCode_ = 0;
        bitField0_ = (bitField0_ & ~0x00000002);
        err_ = "";
        bitField0_ = (bitField0_ & ~0x00000004);
        return this;
      }

      public Builder clone() {
        return create().mergeFrom(buildPartial());
      }

      public com.google.protobuf.Descriptors.Descriptor
          getDescriptorForType() {
        return com.youxigu.dynasty2.chat.proto.ChatMsg.internal_static_tutorial_BadRequest_descriptor;
      }

      public com.youxigu.dynasty2.chat.proto.ChatMsg.BadRequest getDefaultInstanceForType() {
        return com.youxigu.dynasty2.chat.proto.ChatMsg.BadRequest.getDefaultInstance();
      }

      public com.youxigu.dynasty2.chat.proto.ChatMsg.BadRequest build() {
        com.youxigu.dynasty2.chat.proto.ChatMsg.BadRequest result = buildPartial();
        if (!result.isInitialized()) {
          throw newUninitializedMessageException(result);
        }
        return result;
      }

      public com.youxigu.dynasty2.chat.proto.ChatMsg.BadRequest buildPartial() {
        com.youxigu.dynasty2.chat.proto.ChatMsg.BadRequest result = new com.youxigu.dynasty2.chat.proto.ChatMsg.BadRequest(this);
        int from_bitField0_ = bitField0_;
        int to_bitField0_ = 0;
        if (((from_bitField0_ & 0x00000001) == 0x00000001)) {
          to_bitField0_ |= 0x00000001;
        }
        result.cmd_ = cmd_;
        if (((from_bitField0_ & 0x00000002) == 0x00000002)) {
          to_bitField0_ |= 0x00000002;
        }
        result.errCode_ = errCode_;
        if (((from_bitField0_ & 0x00000004) == 0x00000004)) {
          to_bitField0_ |= 0x00000004;
        }
        result.err_ = err_;
        result.bitField0_ = to_bitField0_;
        onBuilt();
        return result;
      }

      public Builder mergeFrom(com.google.protobuf.Message other) {
        if (other instanceof com.youxigu.dynasty2.chat.proto.ChatMsg.BadRequest) {
          return mergeFrom((com.youxigu.dynasty2.chat.proto.ChatMsg.BadRequest)other);
        } else {
          super.mergeFrom(other);
          return this;
        }
      }

      public Builder mergeFrom(com.youxigu.dynasty2.chat.proto.ChatMsg.BadRequest other) {
        if (other == com.youxigu.dynasty2.chat.proto.ChatMsg.BadRequest.getDefaultInstance()) return this;
        if (other.hasCmd()) {
          setCmd(other.getCmd());
        }
        if (other.hasErrCode()) {
          setErrCode(other.getErrCode());
        }
        if (other.hasErr()) {
          bitField0_ |= 0x00000004;
          err_ = other.err_;
          onChanged();
        }
        this.mergeUnknownFields(other.getUnknownFields());
        return this;
      }

      public final boolean isInitialized() {
        if (!hasCmd()) {
          
          return false;
        }
        if (!hasErrCode()) {
          
          return false;
        }
        if (!hasErr()) {
          
          return false;
        }
        return true;
      }

      public Builder mergeFrom(
          com.google.protobuf.CodedInputStream input,
          com.google.protobuf.ExtensionRegistryLite extensionRegistry)
          throws java.io.IOException {
        com.youxigu.dynasty2.chat.proto.ChatMsg.BadRequest parsedMessage = null;
        try {
          parsedMessage = PARSER.parsePartialFrom(input, extensionRegistry);
        } catch (com.google.protobuf.InvalidProtocolBufferException e) {
          parsedMessage = (com.youxigu.dynasty2.chat.proto.ChatMsg.BadRequest) e.getUnfinishedMessage();
          throw e;
        } finally {
          if (parsedMessage != null) {
            mergeFrom(parsedMessage);
          }
        }
        return this;
      }
      private int bitField0_;

      // required int32 cmd = 1;
      private int cmd_ ;
      /**
       * <code>required int32 cmd = 1;</code>
       */
      public boolean hasCmd() {
        return ((bitField0_ & 0x00000001) == 0x00000001);
      }
      /**
       * <code>required int32 cmd = 1;</code>
       */
      public int getCmd() {
        return cmd_;
      }
      /**
       * <code>required int32 cmd = 1;</code>
       */
      public Builder setCmd(int value) {
        bitField0_ |= 0x00000001;
        cmd_ = value;
        onChanged();
        return this;
      }
      /**
       * <code>required int32 cmd = 1;</code>
       */
      public Builder clearCmd() {
        bitField0_ = (bitField0_ & ~0x00000001);
        cmd_ = 0;
        onChanged();
        return this;
      }

      // required int32 errCode = 2;
      private int errCode_ ;
      /**
       * <code>required int32 errCode = 2;</code>
       */
      public boolean hasErrCode() {
        return ((bitField0_ & 0x00000002) == 0x00000002);
      }
      /**
       * <code>required int32 errCode = 2;</code>
       */
      public int getErrCode() {
        return errCode_;
      }
      /**
       * <code>required int32 errCode = 2;</code>
       */
      public Builder setErrCode(int value) {
        bitField0_ |= 0x00000002;
        errCode_ = value;
        onChanged();
        return this;
      }
      /**
       * <code>required int32 errCode = 2;</code>
       */
      public Builder clearErrCode() {
        bitField0_ = (bitField0_ & ~0x00000002);
        errCode_ = 0;
        onChanged();
        return this;
      }

      // required string err = 3;
      private java.lang.Object err_ = "";
      /**
       * <code>required string err = 3;</code>
       */
      public boolean hasErr() {
        return ((bitField0_ & 0x00000004) == 0x00000004);
      }
      /**
       * <code>required string err = 3;</code>
       */
      public java.lang.String getErr() {
        java.lang.Object ref = err_;
        if (!(ref instanceof java.lang.String)) {
          java.lang.String s = ((com.google.protobuf.ByteString) ref)
              .toStringUtf8();
          err_ = s;
          return s;
        } else {
          return (java.lang.String) ref;
        }
      }
      /**
       * <code>required string err = 3;</code>
       */
      public com.google.protobuf.ByteString
          getErrBytes() {
        java.lang.Object ref = err_;
        if (ref instanceof String) {
          com.google.protobuf.ByteString b = 
              com.google.protobuf.ByteString.copyFromUtf8(
                  (java.lang.String) ref);
          err_ = b;
          return b;
        } else {
          return (com.google.protobuf.ByteString) ref;
        }
      }
      /**
       * <code>required string err = 3;</code>
       */
      public Builder setErr(
          java.lang.String value) {
        if (value == null) {
    throw new NullPointerException();
  }
  bitField0_ |= 0x00000004;
        err_ = value;
        onChanged();
        return this;
      }
      /**
       * <code>required string err = 3;</code>
       */
      public Builder clearErr() {
        bitField0_ = (bitField0_ & ~0x00000004);
        err_ = getDefaultInstance().getErr();
        onChanged();
        return this;
      }
      /**
       * <code>required string err = 3;</code>
       */
      public Builder setErrBytes(
          com.google.protobuf.ByteString value) {
        if (value == null) {
    throw new NullPointerException();
  }
  bitField0_ |= 0x00000004;
        err_ = value;
        onChanged();
        return this;
      }

      // @@protoc_insertion_point(builder_scope:tutorial.BadRequest)
    }

    static {
      defaultInstance = new BadRequest(true);
      defaultInstance.initFields();
    }

    // @@protoc_insertion_point(class_scope:tutorial.BadRequest)
  }

  public interface SyncStatOrBuilder
      extends com.google.protobuf.MessageOrBuilder {

    // required int64 id = 1;
    /**
     * <code>required int64 id = 1;</code>
     */
    boolean hasId();
    /**
     * <code>required int64 id = 1;</code>
     */
    long getId();

    // required int32 stat = 2 [default = 1];
    /**
     * <code>required int32 stat = 2 [default = 1];</code>
     */
    boolean hasStat();
    /**
     * <code>required int32 stat = 2 [default = 1];</code>
     */
    int getStat();
  }
  /**
   * Protobuf type {@code tutorial.SyncStat}
   *
   * <pre>
   *同步请求标志
   * </pre>
   */
  public static final class SyncStat extends
      com.google.protobuf.GeneratedMessage
      implements SyncStatOrBuilder {
    // Use SyncStat.newBuilder() to construct.
    private SyncStat(com.google.protobuf.GeneratedMessage.Builder<?> builder) {
      super(builder);
      this.unknownFields = builder.getUnknownFields();
    }
    private SyncStat(boolean noInit) { this.unknownFields = com.google.protobuf.UnknownFieldSet.getDefaultInstance(); }

    private static final SyncStat defaultInstance;
    public static SyncStat getDefaultInstance() {
      return defaultInstance;
    }

    public SyncStat getDefaultInstanceForType() {
      return defaultInstance;
    }

    private final com.google.protobuf.UnknownFieldSet unknownFields;
    @java.lang.Override
    public final com.google.protobuf.UnknownFieldSet
        getUnknownFields() {
      return this.unknownFields;
    }
    private SyncStat(
        com.google.protobuf.CodedInputStream input,
        com.google.protobuf.ExtensionRegistryLite extensionRegistry)
        throws com.google.protobuf.InvalidProtocolBufferException {
      initFields();
      int mutable_bitField0_ = 0;
      com.google.protobuf.UnknownFieldSet.Builder unknownFields =
          com.google.protobuf.UnknownFieldSet.newBuilder();
      try {
        boolean done = false;
        while (!done) {
          int tag = input.readTag();
          switch (tag) {
            case 0:
              done = true;
              break;
            default: {
              if (!parseUnknownField(input, unknownFields,
                                     extensionRegistry, tag)) {
                done = true;
              }
              break;
            }
            case 8: {
              bitField0_ |= 0x00000001;
              id_ = input.readInt64();
              break;
            }
            case 16: {
              bitField0_ |= 0x00000002;
              stat_ = input.readInt32();
              break;
            }
          }
        }
      } catch (com.google.protobuf.InvalidProtocolBufferException e) {
        throw e.setUnfinishedMessage(this);
      } catch (java.io.IOException e) {
        throw new com.google.protobuf.InvalidProtocolBufferException(
            e.getMessage()).setUnfinishedMessage(this);
      } finally {
        this.unknownFields = unknownFields.build();
        makeExtensionsImmutable();
      }
    }
    public static final com.google.protobuf.Descriptors.Descriptor
        getDescriptor() {
      return com.youxigu.dynasty2.chat.proto.ChatMsg.internal_static_tutorial_SyncStat_descriptor;
    }

    protected com.google.protobuf.GeneratedMessage.FieldAccessorTable
        internalGetFieldAccessorTable() {
      return com.youxigu.dynasty2.chat.proto.ChatMsg.internal_static_tutorial_SyncStat_fieldAccessorTable
          .ensureFieldAccessorsInitialized(
              com.youxigu.dynasty2.chat.proto.ChatMsg.SyncStat.class, com.youxigu.dynasty2.chat.proto.ChatMsg.SyncStat.Builder.class);
    }

    public static com.google.protobuf.Parser<SyncStat> PARSER =
        new com.google.protobuf.AbstractParser<SyncStat>() {
      public SyncStat parsePartialFrom(
          com.google.protobuf.CodedInputStream input,
          com.google.protobuf.ExtensionRegistryLite extensionRegistry)
          throws com.google.protobuf.InvalidProtocolBufferException {
        return new SyncStat(input, extensionRegistry);
      }
    };

    @java.lang.Override
    public com.google.protobuf.Parser<SyncStat> getParserForType() {
      return PARSER;
    }

    private int bitField0_;
    // required int64 id = 1;
    public static final int ID_FIELD_NUMBER = 1;
    private long id_;
    /**
     * <code>required int64 id = 1;</code>
     */
    public boolean hasId() {
      return ((bitField0_ & 0x00000001) == 0x00000001);
    }
    /**
     * <code>required int64 id = 1;</code>
     */
    public long getId() {
      return id_;
    }

    // required int32 stat = 2 [default = 1];
    public static final int STAT_FIELD_NUMBER = 2;
    private int stat_;
    /**
     * <code>required int32 stat = 2 [default = 1];</code>
     */
    public boolean hasStat() {
      return ((bitField0_ & 0x00000002) == 0x00000002);
    }
    /**
     * <code>required int32 stat = 2 [default = 1];</code>
     */
    public int getStat() {
      return stat_;
    }

    private void initFields() {
      id_ = 0L;
      stat_ = 1;
    }
    private byte memoizedIsInitialized = -1;
    public final boolean isInitialized() {
      byte isInitialized = memoizedIsInitialized;
      if (isInitialized != -1) return isInitialized == 1;

      if (!hasId()) {
        memoizedIsInitialized = 0;
        return false;
      }
      if (!hasStat()) {
        memoizedIsInitialized = 0;
        return false;
      }
      memoizedIsInitialized = 1;
      return true;
    }

    public void writeTo(com.google.protobuf.CodedOutputStream output)
                        throws java.io.IOException {
      getSerializedSize();
      if (((bitField0_ & 0x00000001) == 0x00000001)) {
        output.writeInt64(1, id_);
      }
      if (((bitField0_ & 0x00000002) == 0x00000002)) {
        output.writeInt32(2, stat_);
      }
      getUnknownFields().writeTo(output);
    }

    private int memoizedSerializedSize = -1;
    public int getSerializedSize() {
      int size = memoizedSerializedSize;
      if (size != -1) return size;

      size = 0;
      if (((bitField0_ & 0x00000001) == 0x00000001)) {
        size += com.google.protobuf.CodedOutputStream
          .computeInt64Size(1, id_);
      }
      if (((bitField0_ & 0x00000002) == 0x00000002)) {
        size += com.google.protobuf.CodedOutputStream
          .computeInt32Size(2, stat_);
      }
      size += getUnknownFields().getSerializedSize();
      memoizedSerializedSize = size;
      return size;
    }

    private static final long serialVersionUID = 0L;
    @java.lang.Override
    protected java.lang.Object writeReplace()
        throws java.io.ObjectStreamException {
      return super.writeReplace();
    }

    public static com.youxigu.dynasty2.chat.proto.ChatMsg.SyncStat parseFrom(
        com.google.protobuf.ByteString data)
        throws com.google.protobuf.InvalidProtocolBufferException {
      return PARSER.parseFrom(data);
    }
    public static com.youxigu.dynasty2.chat.proto.ChatMsg.SyncStat parseFrom(
        com.google.protobuf.ByteString data,
        com.google.protobuf.ExtensionRegistryLite extensionRegistry)
        throws com.google.protobuf.InvalidProtocolBufferException {
      return PARSER.parseFrom(data, extensionRegistry);
    }
    public static com.youxigu.dynasty2.chat.proto.ChatMsg.SyncStat parseFrom(byte[] data)
        throws com.google.protobuf.InvalidProtocolBufferException {
      return PARSER.parseFrom(data);
    }
    public static com.youxigu.dynasty2.chat.proto.ChatMsg.SyncStat parseFrom(
        byte[] data,
        com.google.protobuf.ExtensionRegistryLite extensionRegistry)
        throws com.google.protobuf.InvalidProtocolBufferException {
      return PARSER.parseFrom(data, extensionRegistry);
    }
    public static com.youxigu.dynasty2.chat.proto.ChatMsg.SyncStat parseFrom(java.io.InputStream input)
        throws java.io.IOException {
      return PARSER.parseFrom(input);
    }
    public static com.youxigu.dynasty2.chat.proto.ChatMsg.SyncStat parseFrom(
        java.io.InputStream input,
        com.google.protobuf.ExtensionRegistryLite extensionRegistry)
        throws java.io.IOException {
      return PARSER.parseFrom(input, extensionRegistry);
    }
    public static com.youxigu.dynasty2.chat.proto.ChatMsg.SyncStat parseDelimitedFrom(java.io.InputStream input)
        throws java.io.IOException {
      return PARSER.parseDelimitedFrom(input);
    }
    public static com.youxigu.dynasty2.chat.proto.ChatMsg.SyncStat parseDelimitedFrom(
        java.io.InputStream input,
        com.google.protobuf.ExtensionRegistryLite extensionRegistry)
        throws java.io.IOException {
      return PARSER.parseDelimitedFrom(input, extensionRegistry);
    }
    public static com.youxigu.dynasty2.chat.proto.ChatMsg.SyncStat parseFrom(
        com.google.protobuf.CodedInputStream input)
        throws java.io.IOException {
      return PARSER.parseFrom(input);
    }
    public static com.youxigu.dynasty2.chat.proto.ChatMsg.SyncStat parseFrom(
        com.google.protobuf.CodedInputStream input,
        com.google.protobuf.ExtensionRegistryLite extensionRegistry)
        throws java.io.IOException {
      return PARSER.parseFrom(input, extensionRegistry);
    }

    public static Builder newBuilder() { return Builder.create(); }
    public Builder newBuilderForType() { return newBuilder(); }
    public static Builder newBuilder(com.youxigu.dynasty2.chat.proto.ChatMsg.SyncStat prototype) {
      return newBuilder().mergeFrom(prototype);
    }
    public Builder toBuilder() { return newBuilder(this); }

    @java.lang.Override
    protected Builder newBuilderForType(
        com.google.protobuf.GeneratedMessage.BuilderParent parent) {
      Builder builder = new Builder(parent);
      return builder;
    }
    /**
     * Protobuf type {@code tutorial.SyncStat}
     *
     * <pre>
     *同步请求标志
     * </pre>
     */
    public static final class Builder extends
        com.google.protobuf.GeneratedMessage.Builder<Builder>
       implements com.youxigu.dynasty2.chat.proto.ChatMsg.SyncStatOrBuilder {
      public static final com.google.protobuf.Descriptors.Descriptor
          getDescriptor() {
        return com.youxigu.dynasty2.chat.proto.ChatMsg.internal_static_tutorial_SyncStat_descriptor;
      }

      protected com.google.protobuf.GeneratedMessage.FieldAccessorTable
          internalGetFieldAccessorTable() {
        return com.youxigu.dynasty2.chat.proto.ChatMsg.internal_static_tutorial_SyncStat_fieldAccessorTable
            .ensureFieldAccessorsInitialized(
                com.youxigu.dynasty2.chat.proto.ChatMsg.SyncStat.class, com.youxigu.dynasty2.chat.proto.ChatMsg.SyncStat.Builder.class);
      }

      // Construct using com.youxigu.dynasty2.chat.proto.ChatMsg.SyncStat.newBuilder()
      private Builder() {
        maybeForceBuilderInitialization();
      }

      private Builder(
          com.google.protobuf.GeneratedMessage.BuilderParent parent) {
        super(parent);
        maybeForceBuilderInitialization();
      }
      private void maybeForceBuilderInitialization() {
        if (com.google.protobuf.GeneratedMessage.alwaysUseFieldBuilders) {
        }
      }
      private static Builder create() {
        return new Builder();
      }

      public Builder clear() {
        super.clear();
        id_ = 0L;
        bitField0_ = (bitField0_ & ~0x00000001);
        stat_ = 1;
        bitField0_ = (bitField0_ & ~0x00000002);
        return this;
      }

      public Builder clone() {
        return create().mergeFrom(buildPartial());
      }

      public com.google.protobuf.Descriptors.Descriptor
          getDescriptorForType() {
        return com.youxigu.dynasty2.chat.proto.ChatMsg.internal_static_tutorial_SyncStat_descriptor;
      }

      public com.youxigu.dynasty2.chat.proto.ChatMsg.SyncStat getDefaultInstanceForType() {
        return com.youxigu.dynasty2.chat.proto.ChatMsg.SyncStat.getDefaultInstance();
      }

      public com.youxigu.dynasty2.chat.proto.ChatMsg.SyncStat build() {
        com.youxigu.dynasty2.chat.proto.ChatMsg.SyncStat result = buildPartial();
        if (!result.isInitialized()) {
          throw newUninitializedMessageException(result);
        }
        return result;
      }

      public com.youxigu.dynasty2.chat.proto.ChatMsg.SyncStat buildPartial() {
        com.youxigu.dynasty2.chat.proto.ChatMsg.SyncStat result = new com.youxigu.dynasty2.chat.proto.ChatMsg.SyncStat(this);
        int from_bitField0_ = bitField0_;
        int to_bitField0_ = 0;
        if (((from_bitField0_ & 0x00000001) == 0x00000001)) {
          to_bitField0_ |= 0x00000001;
        }
        result.id_ = id_;
        if (((from_bitField0_ & 0x00000002) == 0x00000002)) {
          to_bitField0_ |= 0x00000002;
        }
        result.stat_ = stat_;
        result.bitField0_ = to_bitField0_;
        onBuilt();
        return result;
      }

      public Builder mergeFrom(com.google.protobuf.Message other) {
        if (other instanceof com.youxigu.dynasty2.chat.proto.ChatMsg.SyncStat) {
          return mergeFrom((com.youxigu.dynasty2.chat.proto.ChatMsg.SyncStat)other);
        } else {
          super.mergeFrom(other);
          return this;
        }
      }

      public Builder mergeFrom(com.youxigu.dynasty2.chat.proto.ChatMsg.SyncStat other) {
        if (other == com.youxigu.dynasty2.chat.proto.ChatMsg.SyncStat.getDefaultInstance()) return this;
        if (other.hasId()) {
          setId(other.getId());
        }
        if (other.hasStat()) {
          setStat(other.getStat());
        }
        this.mergeUnknownFields(other.getUnknownFields());
        return this;
      }

      public final boolean isInitialized() {
        if (!hasId()) {
          
          return false;
        }
        if (!hasStat()) {
          
          return false;
        }
        return true;
      }

      public Builder mergeFrom(
          com.google.protobuf.CodedInputStream input,
          com.google.protobuf.ExtensionRegistryLite extensionRegistry)
          throws java.io.IOException {
        com.youxigu.dynasty2.chat.proto.ChatMsg.SyncStat parsedMessage = null;
        try {
          parsedMessage = PARSER.parsePartialFrom(input, extensionRegistry);
        } catch (com.google.protobuf.InvalidProtocolBufferException e) {
          parsedMessage = (com.youxigu.dynasty2.chat.proto.ChatMsg.SyncStat) e.getUnfinishedMessage();
          throw e;
        } finally {
          if (parsedMessage != null) {
            mergeFrom(parsedMessage);
          }
        }
        return this;
      }
      private int bitField0_;

      // required int64 id = 1;
      private long id_ ;
      /**
       * <code>required int64 id = 1;</code>
       */
      public boolean hasId() {
        return ((bitField0_ & 0x00000001) == 0x00000001);
      }
      /**
       * <code>required int64 id = 1;</code>
       */
      public long getId() {
        return id_;
      }
      /**
       * <code>required int64 id = 1;</code>
       */
      public Builder setId(long value) {
        bitField0_ |= 0x00000001;
        id_ = value;
        onChanged();
        return this;
      }
      /**
       * <code>required int64 id = 1;</code>
       */
      public Builder clearId() {
        bitField0_ = (bitField0_ & ~0x00000001);
        id_ = 0L;
        onChanged();
        return this;
      }

      // required int32 stat = 2 [default = 1];
      private int stat_ = 1;
      /**
       * <code>required int32 stat = 2 [default = 1];</code>
       */
      public boolean hasStat() {
        return ((bitField0_ & 0x00000002) == 0x00000002);
      }
      /**
       * <code>required int32 stat = 2 [default = 1];</code>
       */
      public int getStat() {
        return stat_;
      }
      /**
       * <code>required int32 stat = 2 [default = 1];</code>
       */
      public Builder setStat(int value) {
        bitField0_ |= 0x00000002;
        stat_ = value;
        onChanged();
        return this;
      }
      /**
       * <code>required int32 stat = 2 [default = 1];</code>
       */
      public Builder clearStat() {
        bitField0_ = (bitField0_ & ~0x00000002);
        stat_ = 1;
        onChanged();
        return this;
      }

      // @@protoc_insertion_point(builder_scope:tutorial.SyncStat)
    }

    static {
      defaultInstance = new SyncStat(true);
      defaultInstance.initFields();
    }

    // @@protoc_insertion_point(class_scope:tutorial.SyncStat)
  }

  public interface ChatActionReceiveOrBuilder
      extends com.google.protobuf.MessageOrBuilder {

    // required int32 cmd = 1;
    /**
     * <code>required int32 cmd = 1;</code>
     */
    boolean hasCmd();
    /**
     * <code>required int32 cmd = 1;</code>
     */
    int getCmd();

    // required int32 errCode = 2;
    /**
     * <code>required int32 errCode = 2;</code>
     */
    boolean hasErrCode();
    /**
     * <code>required int32 errCode = 2;</code>
     */
    int getErrCode();

    // required string err = 3;
    /**
     * <code>required string err = 3;</code>
     */
    boolean hasErr();
    /**
     * <code>required string err = 3;</code>
     */
    java.lang.String getErr();
    /**
     * <code>required string err = 3;</code>
     */
    com.google.protobuf.ByteString
        getErrBytes();

    // optional int64 toUserId = 4;
    /**
     * <code>optional int64 toUserId = 4;</code>
     */
    boolean hasToUserId();
    /**
     * <code>optional int64 toUserId = 4;</code>
     */
    long getToUserId();

    // optional string toUserName = 5;
    /**
     * <code>optional string toUserName = 5;</code>
     */
    boolean hasToUserName();
    /**
     * <code>optional string toUserName = 5;</code>
     */
    java.lang.String getToUserName();
    /**
     * <code>optional string toUserName = 5;</code>
     */
    com.google.protobuf.ByteString
        getToUserNameBytes();

    // required string channel = 6;
    /**
     * <code>required string channel = 6;</code>
     */
    boolean hasChannel();
    /**
     * <code>required string channel = 6;</code>
     */
    java.lang.String getChannel();
    /**
     * <code>required string channel = 6;</code>
     */
    com.google.protobuf.ByteString
        getChannelBytes();

    // required string context = 7;
    /**
     * <code>required string context = 7;</code>
     */
    boolean hasContext();
    /**
     * <code>required string context = 7;</code>
     */
    java.lang.String getContext();
    /**
     * <code>required string context = 7;</code>
     */
    com.google.protobuf.ByteString
        getContextBytes();

    // optional string channelId = 8;
    /**
     * <code>optional string channelId = 8;</code>
     */
    boolean hasChannelId();
    /**
     * <code>optional string channelId = 8;</code>
     */
    java.lang.String getChannelId();
    /**
     * <code>optional string channelId = 8;</code>
     */
    com.google.protobuf.ByteString
        getChannelIdBytes();
  }
  /**
   * Protobuf type {@code tutorial.ChatActionReceive}
   *
   * <pre>
   *10009 聊天请求
   * </pre>
   */
  public static final class ChatActionReceive extends
      com.google.protobuf.GeneratedMessage
      implements ChatActionReceiveOrBuilder {
    // Use ChatActionReceive.newBuilder() to construct.
    private ChatActionReceive(com.google.protobuf.GeneratedMessage.Builder<?> builder) {
      super(builder);
      this.unknownFields = builder.getUnknownFields();
    }
    private ChatActionReceive(boolean noInit) { this.unknownFields = com.google.protobuf.UnknownFieldSet.getDefaultInstance(); }

    private static final ChatActionReceive defaultInstance;
    public static ChatActionReceive getDefaultInstance() {
      return defaultInstance;
    }

    public ChatActionReceive getDefaultInstanceForType() {
      return defaultInstance;
    }

    private final com.google.protobuf.UnknownFieldSet unknownFields;
    @java.lang.Override
    public final com.google.protobuf.UnknownFieldSet
        getUnknownFields() {
      return this.unknownFields;
    }
    private ChatActionReceive(
        com.google.protobuf.CodedInputStream input,
        com.google.protobuf.ExtensionRegistryLite extensionRegistry)
        throws com.google.protobuf.InvalidProtocolBufferException {
      initFields();
      int mutable_bitField0_ = 0;
      com.google.protobuf.UnknownFieldSet.Builder unknownFields =
          com.google.protobuf.UnknownFieldSet.newBuilder();
      try {
        boolean done = false;
        while (!done) {
          int tag = input.readTag();
          switch (tag) {
            case 0:
              done = true;
              break;
            default: {
              if (!parseUnknownField(input, unknownFields,
                                     extensionRegistry, tag)) {
                done = true;
              }
              break;
            }
            case 8: {
              bitField0_ |= 0x00000001;
              cmd_ = input.readInt32();
              break;
            }
            case 16: {
              bitField0_ |= 0x00000002;
              errCode_ = input.readInt32();
              break;
            }
            case 26: {
              bitField0_ |= 0x00000004;
              err_ = input.readBytes();
              break;
            }
            case 32: {
              bitField0_ |= 0x00000008;
              toUserId_ = input.readInt64();
              break;
            }
            case 42: {
              bitField0_ |= 0x00000010;
              toUserName_ = input.readBytes();
              break;
            }
            case 50: {
              bitField0_ |= 0x00000020;
              channel_ = input.readBytes();
              break;
            }
            case 58: {
              bitField0_ |= 0x00000040;
              context_ = input.readBytes();
              break;
            }
            case 66: {
              bitField0_ |= 0x00000080;
              channelId_ = input.readBytes();
              break;
            }
          }
        }
      } catch (com.google.protobuf.InvalidProtocolBufferException e) {
        throw e.setUnfinishedMessage(this);
      } catch (java.io.IOException e) {
        throw new com.google.protobuf.InvalidProtocolBufferException(
            e.getMessage()).setUnfinishedMessage(this);
      } finally {
        this.unknownFields = unknownFields.build();
        makeExtensionsImmutable();
      }
    }
    public static final com.google.protobuf.Descriptors.Descriptor
        getDescriptor() {
      return com.youxigu.dynasty2.chat.proto.ChatMsg.internal_static_tutorial_ChatActionReceive_descriptor;
    }

    protected com.google.protobuf.GeneratedMessage.FieldAccessorTable
        internalGetFieldAccessorTable() {
      return com.youxigu.dynasty2.chat.proto.ChatMsg.internal_static_tutorial_ChatActionReceive_fieldAccessorTable
          .ensureFieldAccessorsInitialized(
              com.youxigu.dynasty2.chat.proto.ChatMsg.ChatActionReceive.class, com.youxigu.dynasty2.chat.proto.ChatMsg.ChatActionReceive.Builder.class);
    }

    public static com.google.protobuf.Parser<ChatActionReceive> PARSER =
        new com.google.protobuf.AbstractParser<ChatActionReceive>() {
      public ChatActionReceive parsePartialFrom(
          com.google.protobuf.CodedInputStream input,
          com.google.protobuf.ExtensionRegistryLite extensionRegistry)
          throws com.google.protobuf.InvalidProtocolBufferException {
        return new ChatActionReceive(input, extensionRegistry);
      }
    };

    @java.lang.Override
    public com.google.protobuf.Parser<ChatActionReceive> getParserForType() {
      return PARSER;
    }

    private int bitField0_;
    // required int32 cmd = 1;
    public static final int CMD_FIELD_NUMBER = 1;
    private int cmd_;
    /**
     * <code>required int32 cmd = 1;</code>
     */
    public boolean hasCmd() {
      return ((bitField0_ & 0x00000001) == 0x00000001);
    }
    /**
     * <code>required int32 cmd = 1;</code>
     */
    public int getCmd() {
      return cmd_;
    }

    // required int32 errCode = 2;
    public static final int ERRCODE_FIELD_NUMBER = 2;
    private int errCode_;
    /**
     * <code>required int32 errCode = 2;</code>
     */
    public boolean hasErrCode() {
      return ((bitField0_ & 0x00000002) == 0x00000002);
    }
    /**
     * <code>required int32 errCode = 2;</code>
     */
    public int getErrCode() {
      return errCode_;
    }

    // required string err = 3;
    public static final int ERR_FIELD_NUMBER = 3;
    private java.lang.Object err_;
    /**
     * <code>required string err = 3;</code>
     */
    public boolean hasErr() {
      return ((bitField0_ & 0x00000004) == 0x00000004);
    }
    /**
     * <code>required string err = 3;</code>
     */
    public java.lang.String getErr() {
      java.lang.Object ref = err_;
      if (ref instanceof java.lang.String) {
        return (java.lang.String) ref;
      } else {
        com.google.protobuf.ByteString bs = 
            (com.google.protobuf.ByteString) ref;
        java.lang.String s = bs.toStringUtf8();
        if (bs.isValidUtf8()) {
          err_ = s;
        }
        return s;
      }
    }
    /**
     * <code>required string err = 3;</code>
     */
    public com.google.protobuf.ByteString
        getErrBytes() {
      java.lang.Object ref = err_;
      if (ref instanceof java.lang.String) {
        com.google.protobuf.ByteString b = 
            com.google.protobuf.ByteString.copyFromUtf8(
                (java.lang.String) ref);
        err_ = b;
        return b;
      } else {
        return (com.google.protobuf.ByteString) ref;
      }
    }

    // optional int64 toUserId = 4;
    public static final int TOUSERID_FIELD_NUMBER = 4;
    private long toUserId_;
    /**
     * <code>optional int64 toUserId = 4;</code>
     */
    public boolean hasToUserId() {
      return ((bitField0_ & 0x00000008) == 0x00000008);
    }
    /**
     * <code>optional int64 toUserId = 4;</code>
     */
    public long getToUserId() {
      return toUserId_;
    }

    // optional string toUserName = 5;
    public static final int TOUSERNAME_FIELD_NUMBER = 5;
    private java.lang.Object toUserName_;
    /**
     * <code>optional string toUserName = 5;</code>
     */
    public boolean hasToUserName() {
      return ((bitField0_ & 0x00000010) == 0x00000010);
    }
    /**
     * <code>optional string toUserName = 5;</code>
     */
    public java.lang.String getToUserName() {
      java.lang.Object ref = toUserName_;
      if (ref instanceof java.lang.String) {
        return (java.lang.String) ref;
      } else {
        com.google.protobuf.ByteString bs = 
            (com.google.protobuf.ByteString) ref;
        java.lang.String s = bs.toStringUtf8();
        if (bs.isValidUtf8()) {
          toUserName_ = s;
        }
        return s;
      }
    }
    /**
     * <code>optional string toUserName = 5;</code>
     */
    public com.google.protobuf.ByteString
        getToUserNameBytes() {
      java.lang.Object ref = toUserName_;
      if (ref instanceof java.lang.String) {
        com.google.protobuf.ByteString b = 
            com.google.protobuf.ByteString.copyFromUtf8(
                (java.lang.String) ref);
        toUserName_ = b;
        return b;
      } else {
        return (com.google.protobuf.ByteString) ref;
      }
    }

    // required string channel = 6;
    public static final int CHANNEL_FIELD_NUMBER = 6;
    private java.lang.Object channel_;
    /**
     * <code>required string channel = 6;</code>
     */
    public boolean hasChannel() {
      return ((bitField0_ & 0x00000020) == 0x00000020);
    }
    /**
     * <code>required string channel = 6;</code>
     */
    public java.lang.String getChannel() {
      java.lang.Object ref = channel_;
      if (ref instanceof java.lang.String) {
        return (java.lang.String) ref;
      } else {
        com.google.protobuf.ByteString bs = 
            (com.google.protobuf.ByteString) ref;
        java.lang.String s = bs.toStringUtf8();
        if (bs.isValidUtf8()) {
          channel_ = s;
        }
        return s;
      }
    }
    /**
     * <code>required string channel = 6;</code>
     */
    public com.google.protobuf.ByteString
        getChannelBytes() {
      java.lang.Object ref = channel_;
      if (ref instanceof java.lang.String) {
        com.google.protobuf.ByteString b = 
            com.google.protobuf.ByteString.copyFromUtf8(
                (java.lang.String) ref);
        channel_ = b;
        return b;
      } else {
        return (com.google.protobuf.ByteString) ref;
      }
    }

    // required string context = 7;
    public static final int CONTEXT_FIELD_NUMBER = 7;
    private java.lang.Object context_;
    /**
     * <code>required string context = 7;</code>
     */
    public boolean hasContext() {
      return ((bitField0_ & 0x00000040) == 0x00000040);
    }
    /**
     * <code>required string context = 7;</code>
     */
    public java.lang.String getContext() {
      java.lang.Object ref = context_;
      if (ref instanceof java.lang.String) {
        return (java.lang.String) ref;
      } else {
        com.google.protobuf.ByteString bs = 
            (com.google.protobuf.ByteString) ref;
        java.lang.String s = bs.toStringUtf8();
        if (bs.isValidUtf8()) {
          context_ = s;
        }
        return s;
      }
    }
    /**
     * <code>required string context = 7;</code>
     */
    public com.google.protobuf.ByteString
        getContextBytes() {
      java.lang.Object ref = context_;
      if (ref instanceof java.lang.String) {
        com.google.protobuf.ByteString b = 
            com.google.protobuf.ByteString.copyFromUtf8(
                (java.lang.String) ref);
        context_ = b;
        return b;
      } else {
        return (com.google.protobuf.ByteString) ref;
      }
    }

    // optional string channelId = 8;
    public static final int CHANNELID_FIELD_NUMBER = 8;
    private java.lang.Object channelId_;
    /**
     * <code>optional string channelId = 8;</code>
     */
    public boolean hasChannelId() {
      return ((bitField0_ & 0x00000080) == 0x00000080);
    }
    /**
     * <code>optional string channelId = 8;</code>
     */
    public java.lang.String getChannelId() {
      java.lang.Object ref = channelId_;
      if (ref instanceof java.lang.String) {
        return (java.lang.String) ref;
      } else {
        com.google.protobuf.ByteString bs = 
            (com.google.protobuf.ByteString) ref;
        java.lang.String s = bs.toStringUtf8();
        if (bs.isValidUtf8()) {
          channelId_ = s;
        }
        return s;
      }
    }
    /**
     * <code>optional string channelId = 8;</code>
     */
    public com.google.protobuf.ByteString
        getChannelIdBytes() {
      java.lang.Object ref = channelId_;
      if (ref instanceof java.lang.String) {
        com.google.protobuf.ByteString b = 
            com.google.protobuf.ByteString.copyFromUtf8(
                (java.lang.String) ref);
        channelId_ = b;
        return b;
      } else {
        return (com.google.protobuf.ByteString) ref;
      }
    }

    private void initFields() {
      cmd_ = 0;
      errCode_ = 0;
      err_ = "";
      toUserId_ = 0L;
      toUserName_ = "";
      channel_ = "";
      context_ = "";
      channelId_ = "";
    }
    private byte memoizedIsInitialized = -1;
    public final boolean isInitialized() {
      byte isInitialized = memoizedIsInitialized;
      if (isInitialized != -1) return isInitialized == 1;

      if (!hasCmd()) {
        memoizedIsInitialized = 0;
        return false;
      }
      if (!hasErrCode()) {
        memoizedIsInitialized = 0;
        return false;
      }
      if (!hasErr()) {
        memoizedIsInitialized = 0;
        return false;
      }
      if (!hasChannel()) {
        memoizedIsInitialized = 0;
        return false;
      }
      if (!hasContext()) {
        memoizedIsInitialized = 0;
        return false;
      }
      memoizedIsInitialized = 1;
      return true;
    }

    public void writeTo(com.google.protobuf.CodedOutputStream output)
                        throws java.io.IOException {
      getSerializedSize();
      if (((bitField0_ & 0x00000001) == 0x00000001)) {
        output.writeInt32(1, cmd_);
      }
      if (((bitField0_ & 0x00000002) == 0x00000002)) {
        output.writeInt32(2, errCode_);
      }
      if (((bitField0_ & 0x00000004) == 0x00000004)) {
        output.writeBytes(3, getErrBytes());
      }
      if (((bitField0_ & 0x00000008) == 0x00000008)) {
        output.writeInt64(4, toUserId_);
      }
      if (((bitField0_ & 0x00000010) == 0x00000010)) {
        output.writeBytes(5, getToUserNameBytes());
      }
      if (((bitField0_ & 0x00000020) == 0x00000020)) {
        output.writeBytes(6, getChannelBytes());
      }
      if (((bitField0_ & 0x00000040) == 0x00000040)) {
        output.writeBytes(7, getContextBytes());
      }
      if (((bitField0_ & 0x00000080) == 0x00000080)) {
        output.writeBytes(8, getChannelIdBytes());
      }
      getUnknownFields().writeTo(output);
    }

    private int memoizedSerializedSize = -1;
    public int getSerializedSize() {
      int size = memoizedSerializedSize;
      if (size != -1) return size;

      size = 0;
      if (((bitField0_ & 0x00000001) == 0x00000001)) {
        size += com.google.protobuf.CodedOutputStream
          .computeInt32Size(1, cmd_);
      }
      if (((bitField0_ & 0x00000002) == 0x00000002)) {
        size += com.google.protobuf.CodedOutputStream
          .computeInt32Size(2, errCode_);
      }
      if (((bitField0_ & 0x00000004) == 0x00000004)) {
        size += com.google.protobuf.CodedOutputStream
          .computeBytesSize(3, getErrBytes());
      }
      if (((bitField0_ & 0x00000008) == 0x00000008)) {
        size += com.google.protobuf.CodedOutputStream
          .computeInt64Size(4, toUserId_);
      }
      if (((bitField0_ & 0x00000010) == 0x00000010)) {
        size += com.google.protobuf.CodedOutputStream
          .computeBytesSize(5, getToUserNameBytes());
      }
      if (((bitField0_ & 0x00000020) == 0x00000020)) {
        size += com.google.protobuf.CodedOutputStream
          .computeBytesSize(6, getChannelBytes());
      }
      if (((bitField0_ & 0x00000040) == 0x00000040)) {
        size += com.google.protobuf.CodedOutputStream
          .computeBytesSize(7, getContextBytes());
      }
      if (((bitField0_ & 0x00000080) == 0x00000080)) {
        size += com.google.protobuf.CodedOutputStream
          .computeBytesSize(8, getChannelIdBytes());
      }
      size += getUnknownFields().getSerializedSize();
      memoizedSerializedSize = size;
      return size;
    }

    private static final long serialVersionUID = 0L;
    @java.lang.Override
    protected java.lang.Object writeReplace()
        throws java.io.ObjectStreamException {
      return super.writeReplace();
    }

    public static com.youxigu.dynasty2.chat.proto.ChatMsg.ChatActionReceive parseFrom(
        com.google.protobuf.ByteString data)
        throws com.google.protobuf.InvalidProtocolBufferException {
      return PARSER.parseFrom(data);
    }
    public static com.youxigu.dynasty2.chat.proto.ChatMsg.ChatActionReceive parseFrom(
        com.google.protobuf.ByteString data,
        com.google.protobuf.ExtensionRegistryLite extensionRegistry)
        throws com.google.protobuf.InvalidProtocolBufferException {
      return PARSER.parseFrom(data, extensionRegistry);
    }
    public static com.youxigu.dynasty2.chat.proto.ChatMsg.ChatActionReceive parseFrom(byte[] data)
        throws com.google.protobuf.InvalidProtocolBufferException {
      return PARSER.parseFrom(data);
    }
    public static com.youxigu.dynasty2.chat.proto.ChatMsg.ChatActionReceive parseFrom(
        byte[] data,
        com.google.protobuf.ExtensionRegistryLite extensionRegistry)
        throws com.google.protobuf.InvalidProtocolBufferException {
      return PARSER.parseFrom(data, extensionRegistry);
    }
    public static com.youxigu.dynasty2.chat.proto.ChatMsg.ChatActionReceive parseFrom(java.io.InputStream input)
        throws java.io.IOException {
      return PARSER.parseFrom(input);
    }
    public static com.youxigu.dynasty2.chat.proto.ChatMsg.ChatActionReceive parseFrom(
        java.io.InputStream input,
        com.google.protobuf.ExtensionRegistryLite extensionRegistry)
        throws java.io.IOException {
      return PARSER.parseFrom(input, extensionRegistry);
    }
    public static com.youxigu.dynasty2.chat.proto.ChatMsg.ChatActionReceive parseDelimitedFrom(java.io.InputStream input)
        throws java.io.IOException {
      return PARSER.parseDelimitedFrom(input);
    }
    public static com.youxigu.dynasty2.chat.proto.ChatMsg.ChatActionReceive parseDelimitedFrom(
        java.io.InputStream input,
        com.google.protobuf.ExtensionRegistryLite extensionRegistry)
        throws java.io.IOException {
      return PARSER.parseDelimitedFrom(input, extensionRegistry);
    }
    public static com.youxigu.dynasty2.chat.proto.ChatMsg.ChatActionReceive parseFrom(
        com.google.protobuf.CodedInputStream input)
        throws java.io.IOException {
      return PARSER.parseFrom(input);
    }
    public static com.youxigu.dynasty2.chat.proto.ChatMsg.ChatActionReceive parseFrom(
        com.google.protobuf.CodedInputStream input,
        com.google.protobuf.ExtensionRegistryLite extensionRegistry)
        throws java.io.IOException {
      return PARSER.parseFrom(input, extensionRegistry);
    }

    public static Builder newBuilder() { return Builder.create(); }
    public Builder newBuilderForType() { return newBuilder(); }
    public static Builder newBuilder(com.youxigu.dynasty2.chat.proto.ChatMsg.ChatActionReceive prototype) {
      return newBuilder().mergeFrom(prototype);
    }
    public Builder toBuilder() { return newBuilder(this); }

    @java.lang.Override
    protected Builder newBuilderForType(
        com.google.protobuf.GeneratedMessage.BuilderParent parent) {
      Builder builder = new Builder(parent);
      return builder;
    }
    /**
     * Protobuf type {@code tutorial.ChatActionReceive}
     *
     * <pre>
     *10009 聊天请求
     * </pre>
     */
    public static final class Builder extends
        com.google.protobuf.GeneratedMessage.Builder<Builder>
       implements com.youxigu.dynasty2.chat.proto.ChatMsg.ChatActionReceiveOrBuilder {
      public static final com.google.protobuf.Descriptors.Descriptor
          getDescriptor() {
        return com.youxigu.dynasty2.chat.proto.ChatMsg.internal_static_tutorial_ChatActionReceive_descriptor;
      }

      protected com.google.protobuf.GeneratedMessage.FieldAccessorTable
          internalGetFieldAccessorTable() {
        return com.youxigu.dynasty2.chat.proto.ChatMsg.internal_static_tutorial_ChatActionReceive_fieldAccessorTable
            .ensureFieldAccessorsInitialized(
                com.youxigu.dynasty2.chat.proto.ChatMsg.ChatActionReceive.class, com.youxigu.dynasty2.chat.proto.ChatMsg.ChatActionReceive.Builder.class);
      }

      // Construct using com.youxigu.dynasty2.chat.proto.ChatMsg.ChatActionReceive.newBuilder()
      private Builder() {
        maybeForceBuilderInitialization();
      }

      private Builder(
          com.google.protobuf.GeneratedMessage.BuilderParent parent) {
        super(parent);
        maybeForceBuilderInitialization();
      }
      private void maybeForceBuilderInitialization() {
        if (com.google.protobuf.GeneratedMessage.alwaysUseFieldBuilders) {
        }
      }
      private static Builder create() {
        return new Builder();
      }

      public Builder clear() {
        super.clear();
        cmd_ = 0;
        bitField0_ = (bitField0_ & ~0x00000001);
        errCode_ = 0;
        bitField0_ = (bitField0_ & ~0x00000002);
        err_ = "";
        bitField0_ = (bitField0_ & ~0x00000004);
        toUserId_ = 0L;
        bitField0_ = (bitField0_ & ~0x00000008);
        toUserName_ = "";
        bitField0_ = (bitField0_ & ~0x00000010);
        channel_ = "";
        bitField0_ = (bitField0_ & ~0x00000020);
        context_ = "";
        bitField0_ = (bitField0_ & ~0x00000040);
        channelId_ = "";
        bitField0_ = (bitField0_ & ~0x00000080);
        return this;
      }

      public Builder clone() {
        return create().mergeFrom(buildPartial());
      }

      public com.google.protobuf.Descriptors.Descriptor
          getDescriptorForType() {
        return com.youxigu.dynasty2.chat.proto.ChatMsg.internal_static_tutorial_ChatActionReceive_descriptor;
      }

      public com.youxigu.dynasty2.chat.proto.ChatMsg.ChatActionReceive getDefaultInstanceForType() {
        return com.youxigu.dynasty2.chat.proto.ChatMsg.ChatActionReceive.getDefaultInstance();
      }

      public com.youxigu.dynasty2.chat.proto.ChatMsg.ChatActionReceive build() {
        com.youxigu.dynasty2.chat.proto.ChatMsg.ChatActionReceive result = buildPartial();
        if (!result.isInitialized()) {
          throw newUninitializedMessageException(result);
        }
        return result;
      }

      public com.youxigu.dynasty2.chat.proto.ChatMsg.ChatActionReceive buildPartial() {
        com.youxigu.dynasty2.chat.proto.ChatMsg.ChatActionReceive result = new com.youxigu.dynasty2.chat.proto.ChatMsg.ChatActionReceive(this);
        int from_bitField0_ = bitField0_;
        int to_bitField0_ = 0;
        if (((from_bitField0_ & 0x00000001) == 0x00000001)) {
          to_bitField0_ |= 0x00000001;
        }
        result.cmd_ = cmd_;
        if (((from_bitField0_ & 0x00000002) == 0x00000002)) {
          to_bitField0_ |= 0x00000002;
        }
        result.errCode_ = errCode_;
        if (((from_bitField0_ & 0x00000004) == 0x00000004)) {
          to_bitField0_ |= 0x00000004;
        }
        result.err_ = err_;
        if (((from_bitField0_ & 0x00000008) == 0x00000008)) {
          to_bitField0_ |= 0x00000008;
        }
        result.toUserId_ = toUserId_;
        if (((from_bitField0_ & 0x00000010) == 0x00000010)) {
          to_bitField0_ |= 0x00000010;
        }
        result.toUserName_ = toUserName_;
        if (((from_bitField0_ & 0x00000020) == 0x00000020)) {
          to_bitField0_ |= 0x00000020;
        }
        result.channel_ = channel_;
        if (((from_bitField0_ & 0x00000040) == 0x00000040)) {
          to_bitField0_ |= 0x00000040;
        }
        result.context_ = context_;
        if (((from_bitField0_ & 0x00000080) == 0x00000080)) {
          to_bitField0_ |= 0x00000080;
        }
        result.channelId_ = channelId_;
        result.bitField0_ = to_bitField0_;
        onBuilt();
        return result;
      }

      public Builder mergeFrom(com.google.protobuf.Message other) {
        if (other instanceof com.youxigu.dynasty2.chat.proto.ChatMsg.ChatActionReceive) {
          return mergeFrom((com.youxigu.dynasty2.chat.proto.ChatMsg.ChatActionReceive)other);
        } else {
          super.mergeFrom(other);
          return this;
        }
      }

      public Builder mergeFrom(com.youxigu.dynasty2.chat.proto.ChatMsg.ChatActionReceive other) {
        if (other == com.youxigu.dynasty2.chat.proto.ChatMsg.ChatActionReceive.getDefaultInstance()) return this;
        if (other.hasCmd()) {
          setCmd(other.getCmd());
        }
        if (other.hasErrCode()) {
          setErrCode(other.getErrCode());
        }
        if (other.hasErr()) {
          bitField0_ |= 0x00000004;
          err_ = other.err_;
          onChanged();
        }
        if (other.hasToUserId()) {
          setToUserId(other.getToUserId());
        }
        if (other.hasToUserName()) {
          bitField0_ |= 0x00000010;
          toUserName_ = other.toUserName_;
          onChanged();
        }
        if (other.hasChannel()) {
          bitField0_ |= 0x00000020;
          channel_ = other.channel_;
          onChanged();
        }
        if (other.hasContext()) {
          bitField0_ |= 0x00000040;
          context_ = other.context_;
          onChanged();
        }
        if (other.hasChannelId()) {
          bitField0_ |= 0x00000080;
          channelId_ = other.channelId_;
          onChanged();
        }
        this.mergeUnknownFields(other.getUnknownFields());
        return this;
      }

      public final boolean isInitialized() {
        if (!hasCmd()) {
          
          return false;
        }
        if (!hasErrCode()) {
          
          return false;
        }
        if (!hasErr()) {
          
          return false;
        }
        if (!hasChannel()) {
          
          return false;
        }
        if (!hasContext()) {
          
          return false;
        }
        return true;
      }

      public Builder mergeFrom(
          com.google.protobuf.CodedInputStream input,
          com.google.protobuf.ExtensionRegistryLite extensionRegistry)
          throws java.io.IOException {
        com.youxigu.dynasty2.chat.proto.ChatMsg.ChatActionReceive parsedMessage = null;
        try {
          parsedMessage = PARSER.parsePartialFrom(input, extensionRegistry);
        } catch (com.google.protobuf.InvalidProtocolBufferException e) {
          parsedMessage = (com.youxigu.dynasty2.chat.proto.ChatMsg.ChatActionReceive) e.getUnfinishedMessage();
          throw e;
        } finally {
          if (parsedMessage != null) {
            mergeFrom(parsedMessage);
          }
        }
        return this;
      }
      private int bitField0_;

      // required int32 cmd = 1;
      private int cmd_ ;
      /**
       * <code>required int32 cmd = 1;</code>
       */
      public boolean hasCmd() {
        return ((bitField0_ & 0x00000001) == 0x00000001);
      }
      /**
       * <code>required int32 cmd = 1;</code>
       */
      public int getCmd() {
        return cmd_;
      }
      /**
       * <code>required int32 cmd = 1;</code>
       */
      public Builder setCmd(int value) {
        bitField0_ |= 0x00000001;
        cmd_ = value;
        onChanged();
        return this;
      }
      /**
       * <code>required int32 cmd = 1;</code>
       */
      public Builder clearCmd() {
        bitField0_ = (bitField0_ & ~0x00000001);
        cmd_ = 0;
        onChanged();
        return this;
      }

      // required int32 errCode = 2;
      private int errCode_ ;
      /**
       * <code>required int32 errCode = 2;</code>
       */
      public boolean hasErrCode() {
        return ((bitField0_ & 0x00000002) == 0x00000002);
      }
      /**
       * <code>required int32 errCode = 2;</code>
       */
      public int getErrCode() {
        return errCode_;
      }
      /**
       * <code>required int32 errCode = 2;</code>
       */
      public Builder setErrCode(int value) {
        bitField0_ |= 0x00000002;
        errCode_ = value;
        onChanged();
        return this;
      }
      /**
       * <code>required int32 errCode = 2;</code>
       */
      public Builder clearErrCode() {
        bitField0_ = (bitField0_ & ~0x00000002);
        errCode_ = 0;
        onChanged();
        return this;
      }

      // required string err = 3;
      private java.lang.Object err_ = "";
      /**
       * <code>required string err = 3;</code>
       */
      public boolean hasErr() {
        return ((bitField0_ & 0x00000004) == 0x00000004);
      }
      /**
       * <code>required string err = 3;</code>
       */
      public java.lang.String getErr() {
        java.lang.Object ref = err_;
        if (!(ref instanceof java.lang.String)) {
          java.lang.String s = ((com.google.protobuf.ByteString) ref)
              .toStringUtf8();
          err_ = s;
          return s;
        } else {
          return (java.lang.String) ref;
        }
      }
      /**
       * <code>required string err = 3;</code>
       */
      public com.google.protobuf.ByteString
          getErrBytes() {
        java.lang.Object ref = err_;
        if (ref instanceof String) {
          com.google.protobuf.ByteString b = 
              com.google.protobuf.ByteString.copyFromUtf8(
                  (java.lang.String) ref);
          err_ = b;
          return b;
        } else {
          return (com.google.protobuf.ByteString) ref;
        }
      }
      /**
       * <code>required string err = 3;</code>
       */
      public Builder setErr(
          java.lang.String value) {
        if (value == null) {
    throw new NullPointerException();
  }
  bitField0_ |= 0x00000004;
        err_ = value;
        onChanged();
        return this;
      }
      /**
       * <code>required string err = 3;</code>
       */
      public Builder clearErr() {
        bitField0_ = (bitField0_ & ~0x00000004);
        err_ = getDefaultInstance().getErr();
        onChanged();
        return this;
      }
      /**
       * <code>required string err = 3;</code>
       */
      public Builder setErrBytes(
          com.google.protobuf.ByteString value) {
        if (value == null) {
    throw new NullPointerException();
  }
  bitField0_ |= 0x00000004;
        err_ = value;
        onChanged();
        return this;
      }

      // optional int64 toUserId = 4;
      private long toUserId_ ;
      /**
       * <code>optional int64 toUserId = 4;</code>
       */
      public boolean hasToUserId() {
        return ((bitField0_ & 0x00000008) == 0x00000008);
      }
      /**
       * <code>optional int64 toUserId = 4;</code>
       */
      public long getToUserId() {
        return toUserId_;
      }
      /**
       * <code>optional int64 toUserId = 4;</code>
       */
      public Builder setToUserId(long value) {
        bitField0_ |= 0x00000008;
        toUserId_ = value;
        onChanged();
        return this;
      }
      /**
       * <code>optional int64 toUserId = 4;</code>
       */
      public Builder clearToUserId() {
        bitField0_ = (bitField0_ & ~0x00000008);
        toUserId_ = 0L;
        onChanged();
        return this;
      }

      // optional string toUserName = 5;
      private java.lang.Object toUserName_ = "";
      /**
       * <code>optional string toUserName = 5;</code>
       */
      public boolean hasToUserName() {
        return ((bitField0_ & 0x00000010) == 0x00000010);
      }
      /**
       * <code>optional string toUserName = 5;</code>
       */
      public java.lang.String getToUserName() {
        java.lang.Object ref = toUserName_;
        if (!(ref instanceof java.lang.String)) {
          java.lang.String s = ((com.google.protobuf.ByteString) ref)
              .toStringUtf8();
          toUserName_ = s;
          return s;
        } else {
          return (java.lang.String) ref;
        }
      }
      /**
       * <code>optional string toUserName = 5;</code>
       */
      public com.google.protobuf.ByteString
          getToUserNameBytes() {
        java.lang.Object ref = toUserName_;
        if (ref instanceof String) {
          com.google.protobuf.ByteString b = 
              com.google.protobuf.ByteString.copyFromUtf8(
                  (java.lang.String) ref);
          toUserName_ = b;
          return b;
        } else {
          return (com.google.protobuf.ByteString) ref;
        }
      }
      /**
       * <code>optional string toUserName = 5;</code>
       */
      public Builder setToUserName(
          java.lang.String value) {
        if (value == null) {
    throw new NullPointerException();
  }
  bitField0_ |= 0x00000010;
        toUserName_ = value;
        onChanged();
        return this;
      }
      /**
       * <code>optional string toUserName = 5;</code>
       */
      public Builder clearToUserName() {
        bitField0_ = (bitField0_ & ~0x00000010);
        toUserName_ = getDefaultInstance().getToUserName();
        onChanged();
        return this;
      }
      /**
       * <code>optional string toUserName = 5;</code>
       */
      public Builder setToUserNameBytes(
          com.google.protobuf.ByteString value) {
        if (value == null) {
    throw new NullPointerException();
  }
  bitField0_ |= 0x00000010;
        toUserName_ = value;
        onChanged();
        return this;
      }

      // required string channel = 6;
      private java.lang.Object channel_ = "";
      /**
       * <code>required string channel = 6;</code>
       */
      public boolean hasChannel() {
        return ((bitField0_ & 0x00000020) == 0x00000020);
      }
      /**
       * <code>required string channel = 6;</code>
       */
      public java.lang.String getChannel() {
        java.lang.Object ref = channel_;
        if (!(ref instanceof java.lang.String)) {
          java.lang.String s = ((com.google.protobuf.ByteString) ref)
              .toStringUtf8();
          channel_ = s;
          return s;
        } else {
          return (java.lang.String) ref;
        }
      }
      /**
       * <code>required string channel = 6;</code>
       */
      public com.google.protobuf.ByteString
          getChannelBytes() {
        java.lang.Object ref = channel_;
        if (ref instanceof String) {
          com.google.protobuf.ByteString b = 
              com.google.protobuf.ByteString.copyFromUtf8(
                  (java.lang.String) ref);
          channel_ = b;
          return b;
        } else {
          return (com.google.protobuf.ByteString) ref;
        }
      }
      /**
       * <code>required string channel = 6;</code>
       */
      public Builder setChannel(
          java.lang.String value) {
        if (value == null) {
    throw new NullPointerException();
  }
  bitField0_ |= 0x00000020;
        channel_ = value;
        onChanged();
        return this;
      }
      /**
       * <code>required string channel = 6;</code>
       */
      public Builder clearChannel() {
        bitField0_ = (bitField0_ & ~0x00000020);
        channel_ = getDefaultInstance().getChannel();
        onChanged();
        return this;
      }
      /**
       * <code>required string channel = 6;</code>
       */
      public Builder setChannelBytes(
          com.google.protobuf.ByteString value) {
        if (value == null) {
    throw new NullPointerException();
  }
  bitField0_ |= 0x00000020;
        channel_ = value;
        onChanged();
        return this;
      }

      // required string context = 7;
      private java.lang.Object context_ = "";
      /**
       * <code>required string context = 7;</code>
       */
      public boolean hasContext() {
        return ((bitField0_ & 0x00000040) == 0x00000040);
      }
      /**
       * <code>required string context = 7;</code>
       */
      public java.lang.String getContext() {
        java.lang.Object ref = context_;
        if (!(ref instanceof java.lang.String)) {
          java.lang.String s = ((com.google.protobuf.ByteString) ref)
              .toStringUtf8();
          context_ = s;
          return s;
        } else {
          return (java.lang.String) ref;
        }
      }
      /**
       * <code>required string context = 7;</code>
       */
      public com.google.protobuf.ByteString
          getContextBytes() {
        java.lang.Object ref = context_;
        if (ref instanceof String) {
          com.google.protobuf.ByteString b = 
              com.google.protobuf.ByteString.copyFromUtf8(
                  (java.lang.String) ref);
          context_ = b;
          return b;
        } else {
          return (com.google.protobuf.ByteString) ref;
        }
      }
      /**
       * <code>required string context = 7;</code>
       */
      public Builder setContext(
          java.lang.String value) {
        if (value == null) {
    throw new NullPointerException();
  }
  bitField0_ |= 0x00000040;
        context_ = value;
        onChanged();
        return this;
      }
      /**
       * <code>required string context = 7;</code>
       */
      public Builder clearContext() {
        bitField0_ = (bitField0_ & ~0x00000040);
        context_ = getDefaultInstance().getContext();
        onChanged();
        return this;
      }
      /**
       * <code>required string context = 7;</code>
       */
      public Builder setContextBytes(
          com.google.protobuf.ByteString value) {
        if (value == null) {
    throw new NullPointerException();
  }
  bitField0_ |= 0x00000040;
        context_ = value;
        onChanged();
        return this;
      }

      // optional string channelId = 8;
      private java.lang.Object channelId_ = "";
      /**
       * <code>optional string channelId = 8;</code>
       */
      public boolean hasChannelId() {
        return ((bitField0_ & 0x00000080) == 0x00000080);
      }
      /**
       * <code>optional string channelId = 8;</code>
       */
      public java.lang.String getChannelId() {
        java.lang.Object ref = channelId_;
        if (!(ref instanceof java.lang.String)) {
          java.lang.String s = ((com.google.protobuf.ByteString) ref)
              .toStringUtf8();
          channelId_ = s;
          return s;
        } else {
          return (java.lang.String) ref;
        }
      }
      /**
       * <code>optional string channelId = 8;</code>
       */
      public com.google.protobuf.ByteString
          getChannelIdBytes() {
        java.lang.Object ref = channelId_;
        if (ref instanceof String) {
          com.google.protobuf.ByteString b = 
              com.google.protobuf.ByteString.copyFromUtf8(
                  (java.lang.String) ref);
          channelId_ = b;
          return b;
        } else {
          return (com.google.protobuf.ByteString) ref;
        }
      }
      /**
       * <code>optional string channelId = 8;</code>
       */
      public Builder setChannelId(
          java.lang.String value) {
        if (value == null) {
    throw new NullPointerException();
  }
  bitField0_ |= 0x00000080;
        channelId_ = value;
        onChanged();
        return this;
      }
      /**
       * <code>optional string channelId = 8;</code>
       */
      public Builder clearChannelId() {
        bitField0_ = (bitField0_ & ~0x00000080);
        channelId_ = getDefaultInstance().getChannelId();
        onChanged();
        return this;
      }
      /**
       * <code>optional string channelId = 8;</code>
       */
      public Builder setChannelIdBytes(
          com.google.protobuf.ByteString value) {
        if (value == null) {
    throw new NullPointerException();
  }
  bitField0_ |= 0x00000080;
        channelId_ = value;
        onChanged();
        return this;
      }

      // @@protoc_insertion_point(builder_scope:tutorial.ChatActionReceive)
    }

    static {
      defaultInstance = new ChatActionReceive(true);
      defaultInstance.initFields();
    }

    // @@protoc_insertion_point(class_scope:tutorial.ChatActionReceive)
  }

  public interface ChatActionReceiveReturnOrBuilder
      extends com.google.protobuf.MessageOrBuilder {

    // required int32 cmd = 1;
    /**
     * <code>required int32 cmd = 1;</code>
     */
    boolean hasCmd();
    /**
     * <code>required int32 cmd = 1;</code>
     */
    int getCmd();

    // required int32 errCode = 2;
    /**
     * <code>required int32 errCode = 2;</code>
     */
    boolean hasErrCode();
    /**
     * <code>required int32 errCode = 2;</code>
     */
    int getErrCode();

    // required string err = 3;
    /**
     * <code>required string err = 3;</code>
     */
    boolean hasErr();
    /**
     * <code>required string err = 3;</code>
     */
    java.lang.String getErr();
    /**
     * <code>required string err = 3;</code>
     */
    com.google.protobuf.ByteString
        getErrBytes();

    // required int32 requestCmd = 4;
    /**
     * <code>required int32 requestCmd = 4;</code>
     */
    boolean hasRequestCmd();
    /**
     * <code>required int32 requestCmd = 4;</code>
     */
    int getRequestCmd();
  }
  /**
   * Protobuf type {@code tutorial.ChatActionReceiveReturn}
   *
   * <pre>
   *10010 聊天响应
   * </pre>
   */
  public static final class ChatActionReceiveReturn extends
      com.google.protobuf.GeneratedMessage
      implements ChatActionReceiveReturnOrBuilder {
    // Use ChatActionReceiveReturn.newBuilder() to construct.
    private ChatActionReceiveReturn(com.google.protobuf.GeneratedMessage.Builder<?> builder) {
      super(builder);
      this.unknownFields = builder.getUnknownFields();
    }
    private ChatActionReceiveReturn(boolean noInit) { this.unknownFields = com.google.protobuf.UnknownFieldSet.getDefaultInstance(); }

    private static final ChatActionReceiveReturn defaultInstance;
    public static ChatActionReceiveReturn getDefaultInstance() {
      return defaultInstance;
    }

    public ChatActionReceiveReturn getDefaultInstanceForType() {
      return defaultInstance;
    }

    private final com.google.protobuf.UnknownFieldSet unknownFields;
    @java.lang.Override
    public final com.google.protobuf.UnknownFieldSet
        getUnknownFields() {
      return this.unknownFields;
    }
    private ChatActionReceiveReturn(
        com.google.protobuf.CodedInputStream input,
        com.google.protobuf.ExtensionRegistryLite extensionRegistry)
        throws com.google.protobuf.InvalidProtocolBufferException {
      initFields();
      int mutable_bitField0_ = 0;
      com.google.protobuf.UnknownFieldSet.Builder unknownFields =
          com.google.protobuf.UnknownFieldSet.newBuilder();
      try {
        boolean done = false;
        while (!done) {
          int tag = input.readTag();
          switch (tag) {
            case 0:
              done = true;
              break;
            default: {
              if (!parseUnknownField(input, unknownFields,
                                     extensionRegistry, tag)) {
                done = true;
              }
              break;
            }
            case 8: {
              bitField0_ |= 0x00000001;
              cmd_ = input.readInt32();
              break;
            }
            case 16: {
              bitField0_ |= 0x00000002;
              errCode_ = input.readInt32();
              break;
            }
            case 26: {
              bitField0_ |= 0x00000004;
              err_ = input.readBytes();
              break;
            }
            case 32: {
              bitField0_ |= 0x00000008;
              requestCmd_ = input.readInt32();
              break;
            }
          }
        }
      } catch (com.google.protobuf.InvalidProtocolBufferException e) {
        throw e.setUnfinishedMessage(this);
      } catch (java.io.IOException e) {
        throw new com.google.protobuf.InvalidProtocolBufferException(
            e.getMessage()).setUnfinishedMessage(this);
      } finally {
        this.unknownFields = unknownFields.build();
        makeExtensionsImmutable();
      }
    }
    public static final com.google.protobuf.Descriptors.Descriptor
        getDescriptor() {
      return com.youxigu.dynasty2.chat.proto.ChatMsg.internal_static_tutorial_ChatActionReceiveReturn_descriptor;
    }

    protected com.google.protobuf.GeneratedMessage.FieldAccessorTable
        internalGetFieldAccessorTable() {
      return com.youxigu.dynasty2.chat.proto.ChatMsg.internal_static_tutorial_ChatActionReceiveReturn_fieldAccessorTable
          .ensureFieldAccessorsInitialized(
              com.youxigu.dynasty2.chat.proto.ChatMsg.ChatActionReceiveReturn.class, com.youxigu.dynasty2.chat.proto.ChatMsg.ChatActionReceiveReturn.Builder.class);
    }

    public static com.google.protobuf.Parser<ChatActionReceiveReturn> PARSER =
        new com.google.protobuf.AbstractParser<ChatActionReceiveReturn>() {
      public ChatActionReceiveReturn parsePartialFrom(
          com.google.protobuf.CodedInputStream input,
          com.google.protobuf.ExtensionRegistryLite extensionRegistry)
          throws com.google.protobuf.InvalidProtocolBufferException {
        return new ChatActionReceiveReturn(input, extensionRegistry);
      }
    };

    @java.lang.Override
    public com.google.protobuf.Parser<ChatActionReceiveReturn> getParserForType() {
      return PARSER;
    }

    private int bitField0_;
    // required int32 cmd = 1;
    public static final int CMD_FIELD_NUMBER = 1;
    private int cmd_;
    /**
     * <code>required int32 cmd = 1;</code>
     */
    public boolean hasCmd() {
      return ((bitField0_ & 0x00000001) == 0x00000001);
    }
    /**
     * <code>required int32 cmd = 1;</code>
     */
    public int getCmd() {
      return cmd_;
    }

    // required int32 errCode = 2;
    public static final int ERRCODE_FIELD_NUMBER = 2;
    private int errCode_;
    /**
     * <code>required int32 errCode = 2;</code>
     */
    public boolean hasErrCode() {
      return ((bitField0_ & 0x00000002) == 0x00000002);
    }
    /**
     * <code>required int32 errCode = 2;</code>
     */
    public int getErrCode() {
      return errCode_;
    }

    // required string err = 3;
    public static final int ERR_FIELD_NUMBER = 3;
    private java.lang.Object err_;
    /**
     * <code>required string err = 3;</code>
     */
    public boolean hasErr() {
      return ((bitField0_ & 0x00000004) == 0x00000004);
    }
    /**
     * <code>required string err = 3;</code>
     */
    public java.lang.String getErr() {
      java.lang.Object ref = err_;
      if (ref instanceof java.lang.String) {
        return (java.lang.String) ref;
      } else {
        com.google.protobuf.ByteString bs = 
            (com.google.protobuf.ByteString) ref;
        java.lang.String s = bs.toStringUtf8();
        if (bs.isValidUtf8()) {
          err_ = s;
        }
        return s;
      }
    }
    /**
     * <code>required string err = 3;</code>
     */
    public com.google.protobuf.ByteString
        getErrBytes() {
      java.lang.Object ref = err_;
      if (ref instanceof java.lang.String) {
        com.google.protobuf.ByteString b = 
            com.google.protobuf.ByteString.copyFromUtf8(
                (java.lang.String) ref);
        err_ = b;
        return b;
      } else {
        return (com.google.protobuf.ByteString) ref;
      }
    }

    // required int32 requestCmd = 4;
    public static final int REQUESTCMD_FIELD_NUMBER = 4;
    private int requestCmd_;
    /**
     * <code>required int32 requestCmd = 4;</code>
     */
    public boolean hasRequestCmd() {
      return ((bitField0_ & 0x00000008) == 0x00000008);
    }
    /**
     * <code>required int32 requestCmd = 4;</code>
     */
    public int getRequestCmd() {
      return requestCmd_;
    }

    private void initFields() {
      cmd_ = 0;
      errCode_ = 0;
      err_ = "";
      requestCmd_ = 0;
    }
    private byte memoizedIsInitialized = -1;
    public final boolean isInitialized() {
      byte isInitialized = memoizedIsInitialized;
      if (isInitialized != -1) return isInitialized == 1;

      if (!hasCmd()) {
        memoizedIsInitialized = 0;
        return false;
      }
      if (!hasErrCode()) {
        memoizedIsInitialized = 0;
        return false;
      }
      if (!hasErr()) {
        memoizedIsInitialized = 0;
        return false;
      }
      if (!hasRequestCmd()) {
        memoizedIsInitialized = 0;
        return false;
      }
      memoizedIsInitialized = 1;
      return true;
    }

    public void writeTo(com.google.protobuf.CodedOutputStream output)
                        throws java.io.IOException {
      getSerializedSize();
      if (((bitField0_ & 0x00000001) == 0x00000001)) {
        output.writeInt32(1, cmd_);
      }
      if (((bitField0_ & 0x00000002) == 0x00000002)) {
        output.writeInt32(2, errCode_);
      }
      if (((bitField0_ & 0x00000004) == 0x00000004)) {
        output.writeBytes(3, getErrBytes());
      }
      if (((bitField0_ & 0x00000008) == 0x00000008)) {
        output.writeInt32(4, requestCmd_);
      }
      getUnknownFields().writeTo(output);
    }

    private int memoizedSerializedSize = -1;
    public int getSerializedSize() {
      int size = memoizedSerializedSize;
      if (size != -1) return size;

      size = 0;
      if (((bitField0_ & 0x00000001) == 0x00000001)) {
        size += com.google.protobuf.CodedOutputStream
          .computeInt32Size(1, cmd_);
      }
      if (((bitField0_ & 0x00000002) == 0x00000002)) {
        size += com.google.protobuf.CodedOutputStream
          .computeInt32Size(2, errCode_);
      }
      if (((bitField0_ & 0x00000004) == 0x00000004)) {
        size += com.google.protobuf.CodedOutputStream
          .computeBytesSize(3, getErrBytes());
      }
      if (((bitField0_ & 0x00000008) == 0x00000008)) {
        size += com.google.protobuf.CodedOutputStream
          .computeInt32Size(4, requestCmd_);
      }
      size += getUnknownFields().getSerializedSize();
      memoizedSerializedSize = size;
      return size;
    }

    private static final long serialVersionUID = 0L;
    @java.lang.Override
    protected java.lang.Object writeReplace()
        throws java.io.ObjectStreamException {
      return super.writeReplace();
    }

    public static com.youxigu.dynasty2.chat.proto.ChatMsg.ChatActionReceiveReturn parseFrom(
        com.google.protobuf.ByteString data)
        throws com.google.protobuf.InvalidProtocolBufferException {
      return PARSER.parseFrom(data);
    }
    public static com.youxigu.dynasty2.chat.proto.ChatMsg.ChatActionReceiveReturn parseFrom(
        com.google.protobuf.ByteString data,
        com.google.protobuf.ExtensionRegistryLite extensionRegistry)
        throws com.google.protobuf.InvalidProtocolBufferException {
      return PARSER.parseFrom(data, extensionRegistry);
    }
    public static com.youxigu.dynasty2.chat.proto.ChatMsg.ChatActionReceiveReturn parseFrom(byte[] data)
        throws com.google.protobuf.InvalidProtocolBufferException {
      return PARSER.parseFrom(data);
    }
    public static com.youxigu.dynasty2.chat.proto.ChatMsg.ChatActionReceiveReturn parseFrom(
        byte[] data,
        com.google.protobuf.ExtensionRegistryLite extensionRegistry)
        throws com.google.protobuf.InvalidProtocolBufferException {
      return PARSER.parseFrom(data, extensionRegistry);
    }
    public static com.youxigu.dynasty2.chat.proto.ChatMsg.ChatActionReceiveReturn parseFrom(java.io.InputStream input)
        throws java.io.IOException {
      return PARSER.parseFrom(input);
    }
    public static com.youxigu.dynasty2.chat.proto.ChatMsg.ChatActionReceiveReturn parseFrom(
        java.io.InputStream input,
        com.google.protobuf.ExtensionRegistryLite extensionRegistry)
        throws java.io.IOException {
      return PARSER.parseFrom(input, extensionRegistry);
    }
    public static com.youxigu.dynasty2.chat.proto.ChatMsg.ChatActionReceiveReturn parseDelimitedFrom(java.io.InputStream input)
        throws java.io.IOException {
      return PARSER.parseDelimitedFrom(input);
    }
    public static com.youxigu.dynasty2.chat.proto.ChatMsg.ChatActionReceiveReturn parseDelimitedFrom(
        java.io.InputStream input,
        com.google.protobuf.ExtensionRegistryLite extensionRegistry)
        throws java.io.IOException {
      return PARSER.parseDelimitedFrom(input, extensionRegistry);
    }
    public static com.youxigu.dynasty2.chat.proto.ChatMsg.ChatActionReceiveReturn parseFrom(
        com.google.protobuf.CodedInputStream input)
        throws java.io.IOException {
      return PARSER.parseFrom(input);
    }
    public static com.youxigu.dynasty2.chat.proto.ChatMsg.ChatActionReceiveReturn parseFrom(
        com.google.protobuf.CodedInputStream input,
        com.google.protobuf.ExtensionRegistryLite extensionRegistry)
        throws java.io.IOException {
      return PARSER.parseFrom(input, extensionRegistry);
    }

    public static Builder newBuilder() { return Builder.create(); }
    public Builder newBuilderForType() { return newBuilder(); }
    public static Builder newBuilder(com.youxigu.dynasty2.chat.proto.ChatMsg.ChatActionReceiveReturn prototype) {
      return newBuilder().mergeFrom(prototype);
    }
    public Builder toBuilder() { return newBuilder(this); }

    @java.lang.Override
    protected Builder newBuilderForType(
        com.google.protobuf.GeneratedMessage.BuilderParent parent) {
      Builder builder = new Builder(parent);
      return builder;
    }
    /**
     * Protobuf type {@code tutorial.ChatActionReceiveReturn}
     *
     * <pre>
     *10010 聊天响应
     * </pre>
     */
    public static final class Builder extends
        com.google.protobuf.GeneratedMessage.Builder<Builder>
       implements com.youxigu.dynasty2.chat.proto.ChatMsg.ChatActionReceiveReturnOrBuilder {
      public static final com.google.protobuf.Descriptors.Descriptor
          getDescriptor() {
        return com.youxigu.dynasty2.chat.proto.ChatMsg.internal_static_tutorial_ChatActionReceiveReturn_descriptor;
      }

      protected com.google.protobuf.GeneratedMessage.FieldAccessorTable
          internalGetFieldAccessorTable() {
        return com.youxigu.dynasty2.chat.proto.ChatMsg.internal_static_tutorial_ChatActionReceiveReturn_fieldAccessorTable
            .ensureFieldAccessorsInitialized(
                com.youxigu.dynasty2.chat.proto.ChatMsg.ChatActionReceiveReturn.class, com.youxigu.dynasty2.chat.proto.ChatMsg.ChatActionReceiveReturn.Builder.class);
      }

      // Construct using com.youxigu.dynasty2.chat.proto.ChatMsg.ChatActionReceiveReturn.newBuilder()
      private Builder() {
        maybeForceBuilderInitialization();
      }

      private Builder(
          com.google.protobuf.GeneratedMessage.BuilderParent parent) {
        super(parent);
        maybeForceBuilderInitialization();
      }
      private void maybeForceBuilderInitialization() {
        if (com.google.protobuf.GeneratedMessage.alwaysUseFieldBuilders) {
        }
      }
      private static Builder create() {
        return new Builder();
      }

      public Builder clear() {
        super.clear();
        cmd_ = 0;
        bitField0_ = (bitField0_ & ~0x00000001);
        errCode_ = 0;
        bitField0_ = (bitField0_ & ~0x00000002);
        err_ = "";
        bitField0_ = (bitField0_ & ~0x00000004);
        requestCmd_ = 0;
        bitField0_ = (bitField0_ & ~0x00000008);
        return this;
      }

      public Builder clone() {
        return create().mergeFrom(buildPartial());
      }

      public com.google.protobuf.Descriptors.Descriptor
          getDescriptorForType() {
        return com.youxigu.dynasty2.chat.proto.ChatMsg.internal_static_tutorial_ChatActionReceiveReturn_descriptor;
      }

      public com.youxigu.dynasty2.chat.proto.ChatMsg.ChatActionReceiveReturn getDefaultInstanceForType() {
        return com.youxigu.dynasty2.chat.proto.ChatMsg.ChatActionReceiveReturn.getDefaultInstance();
      }

      public com.youxigu.dynasty2.chat.proto.ChatMsg.ChatActionReceiveReturn build() {
        com.youxigu.dynasty2.chat.proto.ChatMsg.ChatActionReceiveReturn result = buildPartial();
        if (!result.isInitialized()) {
          throw newUninitializedMessageException(result);
        }
        return result;
      }

      public com.youxigu.dynasty2.chat.proto.ChatMsg.ChatActionReceiveReturn buildPartial() {
        com.youxigu.dynasty2.chat.proto.ChatMsg.ChatActionReceiveReturn result = new com.youxigu.dynasty2.chat.proto.ChatMsg.ChatActionReceiveReturn(this);
        int from_bitField0_ = bitField0_;
        int to_bitField0_ = 0;
        if (((from_bitField0_ & 0x00000001) == 0x00000001)) {
          to_bitField0_ |= 0x00000001;
        }
        result.cmd_ = cmd_;
        if (((from_bitField0_ & 0x00000002) == 0x00000002)) {
          to_bitField0_ |= 0x00000002;
        }
        result.errCode_ = errCode_;
        if (((from_bitField0_ & 0x00000004) == 0x00000004)) {
          to_bitField0_ |= 0x00000004;
        }
        result.err_ = err_;
        if (((from_bitField0_ & 0x00000008) == 0x00000008)) {
          to_bitField0_ |= 0x00000008;
        }
        result.requestCmd_ = requestCmd_;
        result.bitField0_ = to_bitField0_;
        onBuilt();
        return result;
      }

      public Builder mergeFrom(com.google.protobuf.Message other) {
        if (other instanceof com.youxigu.dynasty2.chat.proto.ChatMsg.ChatActionReceiveReturn) {
          return mergeFrom((com.youxigu.dynasty2.chat.proto.ChatMsg.ChatActionReceiveReturn)other);
        } else {
          super.mergeFrom(other);
          return this;
        }
      }

      public Builder mergeFrom(com.youxigu.dynasty2.chat.proto.ChatMsg.ChatActionReceiveReturn other) {
        if (other == com.youxigu.dynasty2.chat.proto.ChatMsg.ChatActionReceiveReturn.getDefaultInstance()) return this;
        if (other.hasCmd()) {
          setCmd(other.getCmd());
        }
        if (other.hasErrCode()) {
          setErrCode(other.getErrCode());
        }
        if (other.hasErr()) {
          bitField0_ |= 0x00000004;
          err_ = other.err_;
          onChanged();
        }
        if (other.hasRequestCmd()) {
          setRequestCmd(other.getRequestCmd());
        }
        this.mergeUnknownFields(other.getUnknownFields());
        return this;
      }

      public final boolean isInitialized() {
        if (!hasCmd()) {
          
          return false;
        }
        if (!hasErrCode()) {
          
          return false;
        }
        if (!hasErr()) {
          
          return false;
        }
        if (!hasRequestCmd()) {
          
          return false;
        }
        return true;
      }

      public Builder mergeFrom(
          com.google.protobuf.CodedInputStream input,
          com.google.protobuf.ExtensionRegistryLite extensionRegistry)
          throws java.io.IOException {
        com.youxigu.dynasty2.chat.proto.ChatMsg.ChatActionReceiveReturn parsedMessage = null;
        try {
          parsedMessage = PARSER.parsePartialFrom(input, extensionRegistry);
        } catch (com.google.protobuf.InvalidProtocolBufferException e) {
          parsedMessage = (com.youxigu.dynasty2.chat.proto.ChatMsg.ChatActionReceiveReturn) e.getUnfinishedMessage();
          throw e;
        } finally {
          if (parsedMessage != null) {
            mergeFrom(parsedMessage);
          }
        }
        return this;
      }
      private int bitField0_;

      // required int32 cmd = 1;
      private int cmd_ ;
      /**
       * <code>required int32 cmd = 1;</code>
       */
      public boolean hasCmd() {
        return ((bitField0_ & 0x00000001) == 0x00000001);
      }
      /**
       * <code>required int32 cmd = 1;</code>
       */
      public int getCmd() {
        return cmd_;
      }
      /**
       * <code>required int32 cmd = 1;</code>
       */
      public Builder setCmd(int value) {
        bitField0_ |= 0x00000001;
        cmd_ = value;
        onChanged();
        return this;
      }
      /**
       * <code>required int32 cmd = 1;</code>
       */
      public Builder clearCmd() {
        bitField0_ = (bitField0_ & ~0x00000001);
        cmd_ = 0;
        onChanged();
        return this;
      }

      // required int32 errCode = 2;
      private int errCode_ ;
      /**
       * <code>required int32 errCode = 2;</code>
       */
      public boolean hasErrCode() {
        return ((bitField0_ & 0x00000002) == 0x00000002);
      }
      /**
       * <code>required int32 errCode = 2;</code>
       */
      public int getErrCode() {
        return errCode_;
      }
      /**
       * <code>required int32 errCode = 2;</code>
       */
      public Builder setErrCode(int value) {
        bitField0_ |= 0x00000002;
        errCode_ = value;
        onChanged();
        return this;
      }
      /**
       * <code>required int32 errCode = 2;</code>
       */
      public Builder clearErrCode() {
        bitField0_ = (bitField0_ & ~0x00000002);
        errCode_ = 0;
        onChanged();
        return this;
      }

      // required string err = 3;
      private java.lang.Object err_ = "";
      /**
       * <code>required string err = 3;</code>
       */
      public boolean hasErr() {
        return ((bitField0_ & 0x00000004) == 0x00000004);
      }
      /**
       * <code>required string err = 3;</code>
       */
      public java.lang.String getErr() {
        java.lang.Object ref = err_;
        if (!(ref instanceof java.lang.String)) {
          java.lang.String s = ((com.google.protobuf.ByteString) ref)
              .toStringUtf8();
          err_ = s;
          return s;
        } else {
          return (java.lang.String) ref;
        }
      }
      /**
       * <code>required string err = 3;</code>
       */
      public com.google.protobuf.ByteString
          getErrBytes() {
        java.lang.Object ref = err_;
        if (ref instanceof String) {
          com.google.protobuf.ByteString b = 
              com.google.protobuf.ByteString.copyFromUtf8(
                  (java.lang.String) ref);
          err_ = b;
          return b;
        } else {
          return (com.google.protobuf.ByteString) ref;
        }
      }
      /**
       * <code>required string err = 3;</code>
       */
      public Builder setErr(
          java.lang.String value) {
        if (value == null) {
    throw new NullPointerException();
  }
  bitField0_ |= 0x00000004;
        err_ = value;
        onChanged();
        return this;
      }
      /**
       * <code>required string err = 3;</code>
       */
      public Builder clearErr() {
        bitField0_ = (bitField0_ & ~0x00000004);
        err_ = getDefaultInstance().getErr();
        onChanged();
        return this;
      }
      /**
       * <code>required string err = 3;</code>
       */
      public Builder setErrBytes(
          com.google.protobuf.ByteString value) {
        if (value == null) {
    throw new NullPointerException();
  }
  bitField0_ |= 0x00000004;
        err_ = value;
        onChanged();
        return this;
      }

      // required int32 requestCmd = 4;
      private int requestCmd_ ;
      /**
       * <code>required int32 requestCmd = 4;</code>
       */
      public boolean hasRequestCmd() {
        return ((bitField0_ & 0x00000008) == 0x00000008);
      }
      /**
       * <code>required int32 requestCmd = 4;</code>
       */
      public int getRequestCmd() {
        return requestCmd_;
      }
      /**
       * <code>required int32 requestCmd = 4;</code>
       */
      public Builder setRequestCmd(int value) {
        bitField0_ |= 0x00000008;
        requestCmd_ = value;
        onChanged();
        return this;
      }
      /**
       * <code>required int32 requestCmd = 4;</code>
       */
      public Builder clearRequestCmd() {
        bitField0_ = (bitField0_ & ~0x00000008);
        requestCmd_ = 0;
        onChanged();
        return this;
      }

      // @@protoc_insertion_point(builder_scope:tutorial.ChatActionReceiveReturn)
    }

    static {
      defaultInstance = new ChatActionReceiveReturn(true);
      defaultInstance.initFields();
    }

    // @@protoc_insertion_point(class_scope:tutorial.ChatActionReceiveReturn)
  }

  private static com.google.protobuf.Descriptors.Descriptor
    internal_static_tutorial_BadRequest_descriptor;
  private static
    com.google.protobuf.GeneratedMessage.FieldAccessorTable
      internal_static_tutorial_BadRequest_fieldAccessorTable;
  private static com.google.protobuf.Descriptors.Descriptor
    internal_static_tutorial_SyncStat_descriptor;
  private static
    com.google.protobuf.GeneratedMessage.FieldAccessorTable
      internal_static_tutorial_SyncStat_fieldAccessorTable;
  private static com.google.protobuf.Descriptors.Descriptor
    internal_static_tutorial_ChatActionReceive_descriptor;
  private static
    com.google.protobuf.GeneratedMessage.FieldAccessorTable
      internal_static_tutorial_ChatActionReceive_fieldAccessorTable;
  private static com.google.protobuf.Descriptors.Descriptor
    internal_static_tutorial_ChatActionReceiveReturn_descriptor;
  private static
    com.google.protobuf.GeneratedMessage.FieldAccessorTable
      internal_static_tutorial_ChatActionReceiveReturn_fieldAccessorTable;

  public static com.google.protobuf.Descriptors.FileDescriptor
      getDescriptor() {
    return descriptor;
  }
  private static com.google.protobuf.Descriptors.FileDescriptor
      descriptor;
  static {
    java.lang.String[] descriptorData = {
      "\n\rChatMsg.proto\022\010tutorial\"7\n\nBadRequest\022" +
      "\013\n\003cmd\030\001 \002(\005\022\017\n\007errCode\030\002 \002(\005\022\013\n\003err\030\003 \002" +
      "(\t\"\'\n\010SyncStat\022\n\n\002id\030\001 \002(\003\022\017\n\004stat\030\002 \002(\005" +
      ":\0011\"\231\001\n\021ChatActionReceive\022\013\n\003cmd\030\001 \002(\005\022\017" +
      "\n\007errCode\030\002 \002(\005\022\013\n\003err\030\003 \002(\t\022\020\n\010toUserId" +
      "\030\004 \001(\003\022\022\n\ntoUserName\030\005 \001(\t\022\017\n\007channel\030\006 " +
      "\002(\t\022\017\n\007context\030\007 \002(\t\022\021\n\tchannelId\030\010 \001(\t\"" +
      "X\n\027ChatActionReceiveReturn\022\013\n\003cmd\030\001 \002(\005\022" +
      "\017\n\007errCode\030\002 \002(\005\022\013\n\003err\030\003 \002(\t\022\022\n\nrequest" +
      "Cmd\030\004 \002(\005B*\n\037com.youxigu.dynasty2.chat.p",
      "rotoB\007ChatMsg"
    };
    com.google.protobuf.Descriptors.FileDescriptor.InternalDescriptorAssigner assigner =
      new com.google.protobuf.Descriptors.FileDescriptor.InternalDescriptorAssigner() {
        public com.google.protobuf.ExtensionRegistry assignDescriptors(
            com.google.protobuf.Descriptors.FileDescriptor root) {
          descriptor = root;
          internal_static_tutorial_BadRequest_descriptor =
            getDescriptor().getMessageTypes().get(0);
          internal_static_tutorial_BadRequest_fieldAccessorTable = new
            com.google.protobuf.GeneratedMessage.FieldAccessorTable(
              internal_static_tutorial_BadRequest_descriptor,
              new java.lang.String[] { "Cmd", "ErrCode", "Err", });
          internal_static_tutorial_SyncStat_descriptor =
            getDescriptor().getMessageTypes().get(1);
          internal_static_tutorial_SyncStat_fieldAccessorTable = new
            com.google.protobuf.GeneratedMessage.FieldAccessorTable(
              internal_static_tutorial_SyncStat_descriptor,
              new java.lang.String[] { "Id", "Stat", });
          internal_static_tutorial_ChatActionReceive_descriptor =
            getDescriptor().getMessageTypes().get(2);
          internal_static_tutorial_ChatActionReceive_fieldAccessorTable = new
            com.google.protobuf.GeneratedMessage.FieldAccessorTable(
              internal_static_tutorial_ChatActionReceive_descriptor,
              new java.lang.String[] { "Cmd", "ErrCode", "Err", "ToUserId", "ToUserName", "Channel", "Context", "ChannelId", });
          internal_static_tutorial_ChatActionReceiveReturn_descriptor =
            getDescriptor().getMessageTypes().get(3);
          internal_static_tutorial_ChatActionReceiveReturn_fieldAccessorTable = new
            com.google.protobuf.GeneratedMessage.FieldAccessorTable(
              internal_static_tutorial_ChatActionReceiveReturn_descriptor,
              new java.lang.String[] { "Cmd", "ErrCode", "Err", "RequestCmd", });
          return null;
        }
      };
    com.google.protobuf.Descriptors.FileDescriptor
      .internalBuildGeneratedFileFrom(descriptorData,
        new com.google.protobuf.Descriptors.FileDescriptor[] {
        }, assigner);
  }

  // @@protoc_insertion_point(outer_class_scope)
}
View Code

 

 

编解码过滤器NewMutilCodecFactory.java,注意红色位置标记代码

package com.youxigu.wolf.net.codec;

import java.lang.reflect.Method;
import java.util.HashMap;
import java.util.Iterator;
import java.util.Map;
import java.util.Map.Entry;

import org.apache.mina.core.session.IoSession;
import org.apache.mina.filter.codec.ProtocolCodecFactory;
import org.apache.mina.filter.codec.ProtocolDecoder;
import org.apache.mina.filter.codec.ProtocolEncoder;

import com.google.protobuf.Message;

/**
 * 
 * 9个字节协议头+协议体.
 *
 * 协议头1-4字节表示协议长度 =协议体长度+9-4(去掉长度占的4字节)
 * 
 * 协议头第5字节为标志字节:
 *------------------------
 * 该字节的最低位为压缩位:0=协议体未压缩 1=协议体已经压缩,
 * 该字节的低2-4位为协议位:
 * 000=基于AMF3的协议,
 * 001=基于java serial协议
 * 010=基于protobuf协议
 * 5-8位未用,作为以后扩展
 * ------------------------
 *
 * 6-9字节表示命令号
 *
 * 采用网络字节序的整数(高位在前,低位在后)
 * @author Administrator
 *
 */
public class NewMutilCodecFactory implements ProtocolCodecFactory {

    private NewMutliEncoder encoder;
    private NewMutilDecoder decoder;

    //双向cache
    private Map<Integer, Class<? extends Message>> messages;//这个要在配置文件中初始化protobuf pojo和命令号的对应关系
    private Map<Class<? extends Message>, Integer> commands = new HashMap<Class<? extends Message>, Integer>();

    private Map<Integer, Method> methods = new HashMap<Integer, Method>();

    //是否将protobuf转换成Map
    private boolean toMap = true;

    public void setMessages(Map<Integer, Class<? extends Message>> messages) throws NoSuchMethodException,
            SecurityException {
     //注入之后初始化反向映射关系
        this.messages = messages;
        if (messages != null) {
            Iterator<Entry<Integer, Class<? extends Message>>> lit = messages.entrySet().iterator();
            while (lit.hasNext()) {
                Entry<Integer, Class<? extends Message>> entry = lit.next();
                Class<Message> msgClass = (Class<Message>) entry.getValue();
                commands.put(msgClass, entry.getKey());
                Class[] paramsTypes = { byte[].class };
                Method method = msgClass.getMethod("parseFrom", paramsTypes);
                this.methods.put(entry.getKey(), method);

            }
        }
    }

    public NewMutilCodecFactory() {
        encoder = new NewMutliEncoder(this);
        decoder = new NewMutilDecoder(this);
    }

    public void setCompressLen(int compressLen) {
        encoder.setCompressLen(compressLen);
    }

    public Method getMessageDecodeMethod(int cmd) {

        return methods.get(cmd);
    }

    public Class<? extends Message> getMessageClass(int cmd) {

        return messages.get(cmd);
    }

    public int getMessageCommand(Class msgClass) {
        if (commands.containsKey(msgClass)) {
            return commands.get(msgClass);
        } else {
            return -1;
        }
    }

    @Override
    public ProtocolDecoder getDecoder(IoSession session) throws Exception {
        // TODO Auto-generated method stub
        return decoder;
    }

    @Override
    public ProtocolEncoder getEncoder(IoSession session) throws Exception {
        // TODO Auto-generated method stub
        return encoder;
    }

}

 

#配置spring的映射关系,这是mina编解码器注入

<property name="codecFactory">
                    <bean class="com.youxigu.wolf.net.codec.NewMutilCodecFactory">
                            <property name="compressLen" value="${mina.encoder.compressLen:5120}"/>
              
                             <property name="messages">
                                  <map>
                                    <entry key="10009">
                                       <value>com.youxigu.dynasty2.chat.proto.ChatMsg.ChatActionReceive</value>
                                    </entry>
                                  </map>
                            </property>
                    </bean>        
        </property>    

 

解码器NewMutilDecoder.java

package com.youxigu.wolf.net.codec;

import java.io.ByteArrayInputStream;
import java.io.ByteArrayOutputStream;
import java.io.ObjectInputStream;
import java.io.UnsupportedEncodingException;
import java.lang.reflect.Field;
import java.lang.reflect.Method;
import java.util.zip.GZIPInputStream;
import java.util.zip.InflaterInputStream;

import org.apache.mina.core.buffer.BufferDataException;
import org.apache.mina.core.buffer.IoBuffer;
import org.apache.mina.core.session.AttributeKey;
import org.apache.mina.core.session.IoSession;
import org.apache.mina.filter.codec.CumulativeProtocolDecoder;
import org.apache.mina.filter.codec.ProtocolDecoderOutput;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import com.google.protobuf.Message;
import com.youxigu.wolf.net.NodeSessionMgr;

import flex.messaging.io.SerializationContext;
import flex.messaging.io.amf.Amf3Input;

public class NewMutilDecoder extends CumulativeProtocolDecoder {
    private static Logger log = LoggerFactory.getLogger(NewMutilDecoder.class);

    // FLASH安全沙箱标志
    private final AttributeKey POLICY = new AttributeKey(this.getClass(), "policy");
    // 腾讯TGW协议头
    private final AttributeKey TGWHEAD = new AttributeKey(this.getClass(), "TGW");
    private final String securityReq = "<policy-file-request/>";
    private final String security = "<cross-domain-policy><site-control permitted-cross-domain-policies=\"all\"/><allow-access-from domain=\"*\" to-ports=\"*\" /></cross-domain-policy>\0";

    private static SerializationContext context = new SerializationContext();

    protected static Field bsBufField = null;
    static {
        context.createASObjectForMissingType = true;
        try {
            bsBufField = ByteArrayOutputStream.class.getDeclaredField("buf");
            bsBufField.setAccessible(true);
        } catch (Exception e) {
            e.printStackTrace();
        }
    }

    private NewMutilCodecFactory factory;

    public NewMutilDecoder(NewMutilCodecFactory factory) {
        this.factory = factory;
    }

    /**
     * decoder最大长度
     */
    private int maxDecodeLen = 5 * 1024 * 1024;

    public void setMaxDecodeLen(int maxDecodeLen) {
        this.maxDecodeLen = maxDecodeLen;
    }

    // static{
    // context.legacyMap=true;
    // }
    @Override
    protected boolean doDecode(IoSession session, IoBuffer in, ProtocolDecoderOutput out) throws Exception {
        // long time = System.currentTimeMillis();
        if (this.isSecurityRequest(session, in)) {
            // 安全策略请求
            // ASObject asObject = new ASObject();
            // asObject.put("policy", securityReq);
            // out.write(asObject);
            session.write(security);
        } else {
            // 去掉TGW包头
            skipTGWRequest(session, in);
            try {
                while (in.remaining() > 0) {// /这层循环实际上不需要,CumulativeProtocolDecoder已经处理了
                    boolean dataAvai = false;
                    if (session.containsAttribute(NodeSessionMgr.SERVER_TYPE_KEY)) {
                        dataAvai = in.prefixedDataAvailable(4, Integer.MAX_VALUE);
                    } else {
                        dataAvai = in.prefixedDataAvailable(4, maxDecodeLen);
                    }
                    if (dataAvai) {
                        //System.out.println("*****"+in.getInt(in.position()));
                        // 正常Encoder中写入的包头制定长度数据
                        int len = in.getInt();

                        byte flag = in.get();// 标志位

                        // 是否压缩
                        boolean compressed = ((flag & 0x1) == MutliEncoderNew.BIT_COMPRESSED);

                        // //先把需要的字节数读到数组中,防止decode出错后有剩余的字节保留在IoBuffer,使下一个请求解析不了
                        byte bytes[] = null;
                        if ((flag & 0xE) == NewMutliEncoder.BIT_JAVA) {
                            bytes = new byte[len - 1];
                            in.get(bytes, 0, len - 1);
                            javaDecode(out, bytes, compressed);
                        } else if ((flag & 0xE) == NewMutliEncoder.BIT_PROTOBUF) {
                            //增加protobuf
                            int command = in.getInt();// 包的命令字
                            bytes = new byte[len - 5];
                            in.get(bytes, 0, len - 5);
                            protobufDecode(out, bytes, command);
                        } else {
                            bytes = new byte[len - 1];
                            in.get(bytes, 0, len - 1);
                            amf3Decode(out, bytes, compressed);
                        }
                        //System.out.println("========1");
                    } else {
                        // 包长度不正确,等待后续包
                        if (log.isDebugEnabled()) {
                            log.debug("包长度不正确,等待后续包.......");
                        }
                        //System.out.println(":::总长度"+in.getInt(in.position())+",本次接收长度:"+in.remaining());
                        // System.out.println("length is error");
                        return false;
                    }

                }
            } catch (BufferDataException e) {
                log.error("解码数据长度不在限制范围内,丢弃并关闭session.{}", session);
                session.close(true);
                throw e;
            } catch (Exception e) {
                log.error(e.getMessage());
                throw e;
            }
        }
        return true;

    }

    public void amf3Decode(ProtocolDecoderOutput out, byte[] bytes, boolean compressed) throws Exception {

        int len = bytes.length;
        ByteArrayInputStream bios = new ByteArrayInputStream(bytes, 0, len);

        Amf3Input amf3in = null;
        try {
            amf3in = new Amf3Input(context);
            if (compressed) {
                amf3in.setInputStream(new GZIPInputStream(bios));
            } else {
                amf3in.setInputStream(bios);
            }
            Object message = amf3in.readObject();
            if (message != null) {
                out.write(message);
            }

        } finally {
            if (amf3in != null) {
                amf3in.close();
            }
        }

    }

    public void javaDecode(ProtocolDecoderOutput out, byte[] bytes, boolean compressed) throws Exception {
        int len = bytes.length;

        ByteArrayInputStream bios = new ByteArrayInputStream(bytes, 0, len);

        ObjectInputStream ois = null;

        try {
            if (compressed) {
                ois = new ObjectInputStream(new InflaterInputStream(bios));
            } else {
                ois = new ObjectInputStream(bios);
            }
            Object message = ois.readObject();
            if (message != null) {
                out.write(message);
            }

        } finally {
            if (ois != null) {
                ois.close();
            }
        }

        // in.close();

    }

    public void protobufDecode(ProtocolDecoderOutput out, byte[] bytes, int command) throws Exception {
        if (command < 0 || command > Integer.MAX_VALUE) {
            throw new RuntimeException("command:" + command + "没有对应的实现类");
        }

        Class<? extends Message> cls = factory.getMessageClass(command);
        Method m = factory.getMessageDecodeMethod(command);
        if (cls == null || m == null) {
            throw new RuntimeException("command:" + command + "没有对应的实现类");
        }

        Message obj = (Message) m.invoke(null, bytes);// static
        // method
        if (obj != null) {
            out.write(obj);
        }
    }

    private boolean isSecurityRequest(IoSession session, IoBuffer in) {
        Boolean policy = (Boolean) session.getAttribute(POLICY);
        if (policy != null) {
            return false;
        }
        int len = in.limit();
        if (len < 23) {
            // 不够安全沙箱的长度,不设置
            return false;
        }
        int start = in.position();
        byte[] bytes = new byte[len];
        in.get(bytes);// 从IoBuffer中获取数据并放入bytes中
        String request = null;
        try {
            request = new String(bytes, "UTF-8");
        } catch (UnsupportedEncodingException e) {
            request = null;
        }

        boolean result = false;
        if (request != null) {
            result = request.startsWith(securityReq);
        }
        session.setAttribute(POLICY, new Boolean(result));
        if (!result) {
            in.position(start);
        }
        return result;
    }

    /**
     * 腾讯TGW协议 :TGW包头格式为如下:tgw_l7_forward\r\nHost:
     * app12345-54321.qzoneapp.com:8002\r\n\r\n
     * 
     * @param session
     * @param in
     * @return
     */
    private void skipTGWRequest(IoSession session, IoBuffer in) {
        Boolean tgw = (Boolean) session.getAttribute(TGWHEAD);
        if (tgw != null) {
            return;
        }
        int start = in.position();
        int len = in.limit();

        boolean result = false;
        // byte[] bytes = new byte[len];

        int pos = 0;
        if (len > 25) {
            // tgw开始
            if (in.get() == 't' && in.get() == 'g' && in.get() == 'w') {
                while (pos < len - 4) {
                    if (in.get() == '\r') {
                        if (in.get() == '\n') {
                            if (in.get() == '\r') {
                                if (in.get() == '\n') {
                                    result = true;
                                    break;
                                }
                            }
                        }
                    }
                }
            }
        }
        session.setAttribute(TGWHEAD, new Boolean(result));
        if (!result) {
            in.position(start);
        }

    }
}

 

编码器NewMutliEncoder.java

package com.youxigu.wolf.net.codec;

import java.io.ByteArrayOutputStream;
import java.io.IOException;
import java.io.ObjectOutputStream;
import java.lang.reflect.Field;
import java.util.Map;
import java.util.zip.Deflater;
import java.util.zip.GZIPOutputStream;

import org.apache.mina.core.buffer.IoBuffer;
import org.apache.mina.core.session.IoSession;
import org.apache.mina.filter.codec.ProtocolEncoderAdapter;
import org.apache.mina.filter.codec.ProtocolEncoderOutput;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import flex.messaging.io.SerializationContext;
import flex.messaging.io.amf.Amf3Output;

/**
 * 
 * 9个字节协议头+协议体.
 *
 * 协议头1-4字节表示协议长度 =协议体长度+9-4(去掉长度占的4字节)
 * 
 * 协议头第5字节为标志字节:
 *------------------------
 * 该字节的最低位为压缩位:0=协议体未压缩 1=协议体已经压缩,
 * 该字节的低2-4位为协议位:
 * 000=基于AMF3的协议,
 * 001=基于java serial协议
 * 010=基于protobuf协议
 * 5-8位未用,作为以后扩展
 * ------------------------
 *
 * 6-9字节表示命令号
 *
 * 采用网络字节序的整数(高位在前,低位在后)
 * @author Administrator
 *
 */
public class NewMutliEncoder extends ProtocolEncoderAdapter {
    private static Logger log = LoggerFactory.getLogger(MutliEncoderNew.class);
    public static final byte BIT_COMPRESSED = 0x01;
    public static final byte BIT_UNCOMPRESSED = 0x00;

    public static final int HEAD_LEN = 5;
    public static final int PROTOBUF_HEAD_LEN = 9;

    public static final byte BIT_AMF3 = 0x00;
    public static final byte BIT_JAVA = 0x02;
    public static final byte BIT_PROTOBUF = 0x04;

    private static SerializationContext context = new SerializationContext();
    protected static Field bsBufField = null;
    static {
        context.legacyCollection = true;
        context.legacyMap = false;

        try {
            bsBufField = ByteArrayOutputStream.class.getDeclaredField("buf");
            bsBufField.setAccessible(true);
        } catch (Exception e) {
            e.printStackTrace();
        }
    }

    private NewMutilCodecFactory factory;

    public NewMutliEncoder(NewMutilCodecFactory factory) {
        this.factory = factory;
    }

    private static int cachesize = 1024;
    /**
     * 字节数》compressLen压缩,否则不压缩
     */
    private int compressLen = 5120;// 5120;// 5K Integer.MAX_VALUE;// ;

    private int maxSendLen = 0;// 统计的最大消息长度

    // private final AttributeKey DEFLATER = new AttributeKey(getClass(),
    // "deflater");

    public void setCompressLen(int compressLen) {
        this.compressLen = compressLen;
    }

    @Override
    public void encode(IoSession session, Object message, ProtocolEncoderOutput out) throws Exception {
        // long time = System.currentTimeMillis();
        if (message instanceof String) {// flash 安全沙箱或者TGW头不encode,
            String str = (String) message;

            IoBuffer buffer = null;
            if (str.startsWith("tgw_")) {
                byte[] bytes = str.getBytes("GBK");
                buffer = IoBuffer.allocate(bytes.length);
                buffer.put(bytes);
            } else {
                byte[] bytes = str.getBytes("UTF-8");
                buffer = IoBuffer.allocate(bytes.length + 1);
                buffer.put(bytes);
                buffer.put((byte) 0x0);
            }
            buffer.flip();
            out.write(buffer);
        } else {
            byte flag = BIT_AMF3;// 标志位
            boolean isProtoBuf = message instanceof com.google.protobuf.Message;

            // 这里使用的buffer都是非direct的,不用free;
            // TODO:这里默认应该分配多大呢?
            IoBuffer buffer = null;
            int head = 0;
            if (isProtoBuf) {
                //头9个字节被占用
                flag = BIT_PROTOBUF;
                head = PROTOBUF_HEAD_LEN;
            } else {
                //头5个字节被占用
                head = HEAD_LEN;
                buffer = IoBuffer.allocate(256, false);
                buffer.setAutoExpand(true);
                // 留出协议头位置
                buffer.position(head);
            }


            int command = 0;
            if (message instanceof Map || message instanceof IAMF3Message) {
                getAmf3Bytes(buffer, message);
            } else if (isProtoBuf) {
                command = factory.getMessageCommand(message.getClass());
                byte[] bytes = ((com.google.protobuf.Message) message).toByteArray();
                buffer = IoBuffer.allocate(bytes.length + head, false);
                // 留出协议头位置
                buffer.position(head);
                buffer.put(bytes);
            } else {
                flag = BIT_JAVA;
                getJavaBytes(buffer, message);
            }

            // TODO:目前没有处理加密
            // 协议体字节数
            int position = buffer.position();
            int byteLen = position - head;
            // System.out.println("=====len"+byteLen);
            if (log.isInfoEnabled()) {// 由于多线程的原因,这里显示的不完全正确
                if (byteLen > maxSendLen) {
                    log.info("当前发出的最大消息长度:{}byte", byteLen);
                    maxSendLen = byteLen;
                }
            }
            // 四字节长度位,+一字节标志位(第一位为压缩标志位,第二位为加密标志位)
            // 压缩
            if (!isProtoBuf && byteLen > compressLen) {
                // long time = System.currentTimeMillis();
                int oldLen = byteLen;
                flag = (byte) (flag | BIT_COMPRESSED);
                byte[] inputs = buffer.buf().array();
                // // TODO:这里分配多大合适呢?
                // buffer = IoBuffer.allocate(3072, false);
                // buffer.setAutoExpand(true);
                buffer.clear();
                buffer.position(HEAD_LEN);
                if ((flag & 0xE) == MutliEncoderNew.BIT_JAVA) {
                    compressJava(session, inputs, HEAD_LEN, byteLen, buffer);
                } else {
                    compress(session, inputs, HEAD_LEN, byteLen, buffer);
                }
                position = buffer.position();
                byteLen = position - HEAD_LEN;

                if (log.isDebugEnabled()) {
                    log.debug("消息体太长,被压缩,from {} bytes to {} bytes.", oldLen, byteLen);
                }
                // System.out.println("压缩时间:"
                // + (System.currentTimeMillis() - time));
            }

            buffer.position(0);
            // 加入长度字段,长度=数据长度+标志位长度+(ptotobuf cmd)
            buffer.putInt(byteLen + head - 4);
            buffer.put(flag);
            if (isProtoBuf) {
                buffer.putInt(command);
            }
            buffer.position(position);

            buffer.flip();

            out.write(buffer);

        }

        // System.out.println("time="+(System.currentTimeMillis()-time));

    }

    protected void getAmf3Bytes(IoBuffer buffer, Object message) throws Exception {
        Amf3Output amf3out = null;
        try {
            amf3out = new Amf3Output(context);
            amf3out.setOutputStream(new IoBufferOutputStream(buffer));
            amf3out.writeObject(message);
            amf3out.flush();
        } finally {
            if (amf3out != null) {
                amf3out.close();
            }
        }
    }

    protected void getJavaBytes(IoBuffer buffer, Object message) throws Exception {
        ObjectOutputStream oos = null;
        try {
            oos = new ObjectOutputStream(new IoBufferOutputStream(buffer));
            oos.writeObject(message);
            oos.flush();
        } finally {
            if (oos != null) {
                oos.close();
            }
        }
    }

    private void compress(IoSession session, byte[] inputs, int offset, int byteLen, IoBuffer buffer) {

        GZIPOutputStream os = null;
        ByteArrayOutputStream bs = null;
        try {
            bs = new ByteArrayOutputStream(byteLen / 2);
            os = new GZIPOutputStream(bs, cachesize);
            os.write(inputs, offset, byteLen);

            os.flush();
            os.close();
            byte[] buf = (byte[]) bsBufField.get(bs);
            int bufLen = bs.size();
            buffer.put(buf, 0, bufLen);
        } catch (IOException e) {
            e.printStackTrace();
            throw new RuntimeException("IO exception compress data");
        } catch (IllegalArgumentException e) {
            e.printStackTrace();
            throw new RuntimeException("IllegalArgumentException compress data");
        } catch (IllegalAccessException e) {
            e.printStackTrace();
            throw new RuntimeException("IllegalAccessException compress data");
        } finally {
            try {
                if (os != null) {
                    os.close();
                }
            } catch (Exception e) {
            }
        }
    }

    private void compressJava(IoSession session, byte[] inputs, int offset, int byteLen, IoBuffer buffer) {

        Deflater deflater = null;
        try {
            deflater = new Deflater();

            byte[] buf = new byte[cachesize];

            for (int i = 0; i < byteLen; i += cachesize) {
                deflater.setInput(inputs, offset + i, Math.min(cachesize, byteLen - i));
                while (!deflater.needsInput()) {
                    int len = deflater.deflate(buf, 0, cachesize);
                    if (len > 0) {
                        buffer.put(buf, 0, len);
                    }
                }
            }
            if (!deflater.finished()) {
                deflater.finish();
                while (!deflater.finished()) {
                    int len = deflater.deflate(buf, 0, cachesize);
                    if (len > 0) {
                        buffer.put(buf, 0, len);
                    }
                }
            }

        } finally {
            deflater.end();
        }

    }

}

 

到这编解码就已经OK了,优势是做了统一的编解码处理,并不是下发到具体的请求处理方法中做编解码处理,

这里解码对象都是protobuf 中Message接口的实现类的子类,所以我们只需要用反射取出message中cmd,在用cmd找到请求的处理方法,调用就可以了

 

剩下就是在mina的IOHandle里怎么用了

 

posted on 2015-08-26 13:29  dagangzi  阅读(4291)  评论(2编辑  收藏  举报