4、thrift源码分析之_TProtocol协议

 public void writeMessageBegin(TMessage message) throws TException {
    if (strictWrite_) {
      int version = VERSION_1 | message.type;
      writeI32(version);
      writeString(message.name);
      writeI32(message.seqid);
    } else {
      writeString(message.name);
      writeByte(message.type);
      writeI32(message.seqid);
    }
  }
public void writeI32(int i32) throws TException {
    i32out[0] = (byte)(0xff & (i32 >> 24));
    i32out[1] = (byte)(0xff & (i32 >> 16));
    i32out[2] = (byte)(0xff & (i32 >> 8));
    i32out[3] = (byte)(0xff & (i32));
    //这一段代码就说明真正进行网络I/O读写的是TTransport
    trans_.write(i32out, 0, 4);
  }

  我们知道对于RPC框架,通信协议是重要的一环,对于thrift框架来说,thrift定义了一个协议的顶层接口TProtocol,其实TProtocol是一个抽象类并且它内部也维护了一个TTransport,这个协议的作用就是对传输数据格式的封装,实现不同的协议来适合不同场景下的数据传输。

 TProtocol中封装了每一个数据类型读和写,这里的读写是针对网络I/O的读写,真正的网络读写的是TTransport,它主要处理数据的,如对数据格式的调整。

TProtocol是一个抽象方法,为了不让外部实现这个类,所以它私有化了构造方法。

/**
   * Prevent direct instantiation
   */
  @SuppressWarnings("unused")
  private TProtocol() {}
  同时它又提供了能够让父类继承的构造函数。这个构造方法传递了一个参数,TTransport.

  /**
   * Constructor
   */
  protected TProtocol(TTransport trans) {
    trans_ = trans;
  }

  从上面知道,TProtocol这个协议它只是处理数据的,其真正对网络进行读写的是TTransport,所以它维护了一个TTransport 例如TBinaryProtocol


/**
   * Transport
   */
  protected TTransport trans_;
 /**
   * Transport accessor
   */
  public TTransport getTransport() {
    return trans_;
  }
 TProtocol定义了各种数据类型的写方法

 public abstract void writeMessageBegin(TMessage message) throws TException;

  public abstract void writeMessageEnd() throws TException;

  public abstract void writeStructBegin(TStruct struct) throws TException;

  public abstract void writeStructEnd() throws TException;

  public abstract void writeFieldBegin(TField field) throws TException;

  public abstract void writeFieldEnd() throws TException;

  public abstract void writeFieldStop() throws TException;

  public abstract void writeMapBegin(TMap map) throws TException;

  public abstract void writeMapEnd() throws TException;

  public abstract void writeListBegin(TList list) throws TException;

  public abstract void writeListEnd() throws TException;

  public abstract void writeSetBegin(TSet set) throws TException;

  public abstract void writeSetEnd() throws TException;

  public abstract void writeBool(boolean b) throws TException;

  public abstract void writeByte(byte b) throws TException;

  public abstract void writeI16(short i16) throws TException;

  public abstract void writeI32(int i32) throws TException;

  public abstract void writeI64(long i64) throws TException;

  public abstract void writeDouble(double dub) throws TException;

  public abstract void writeString(String str) throws TException;

  public abstract void writeBinary(ByteBuffer buf) throws TException;
  我们可以从上面的抽象方法中可以看出,只要thrift文件支持的数据类型,都有与之相对应的写方法。在上面的方法中,
writeMessageBegin(TMessage message)
可以看到它的参数时TMessage,在thrift中客户端和服务端通信的媒介被封装成了TMessage,TMessage中主要有三个属性

 public final String name;
 public final byte type;
 public final int seqid;
  public TMessage() {
    this("", TType.STOP, 0);
  }
public TMessage(String n, byte t, int s) {
    name = n;
    type = t;
    seqid = s;
  }
 name:功能方法的名称,其实就是thrift文件中定义的服务方法名。如果使用TMessage的无参方法,则name默认为“”

 type:从TMessageType获取的,如果使用TMessage的无参方法,则设置为TType.STOP

public final class TMessageType {
  public static final byte CALL  = 1;
  public static final byte REPLY = 2;
  public static final byte EXCEPTION = 3;
  public static final byte ONEWAY = 4;
}
seqid:用来标示客户端的。

上面的写方法,有Begin和End,所以

 public void write_args(org.apache.thrift.protocol.TProtocol prot) throws org.apache.thrift.TException {
        prot.writeMessageBegin(new org.apache.thrift.protocol.TMessage("getUser", org.apache.thrift.protocol.TMessageType.CALL, 0));
        getUser_args args = new getUser_args();
        args.write(prot);
        prot.writeMessageEnd();
      }

  TProtocol同时也定义了各种数据类型的读方法

public abstract TMessage readMessageBegin() throws TException;

  public abstract void readMessageEnd() throws TException;

  public abstract TStruct readStructBegin() throws TException;

  public abstract void readStructEnd() throws TException;

  public abstract TField readFieldBegin() throws TException;

  public abstract void readFieldEnd() throws TException;

  public abstract TMap readMapBegin() throws TException;

  public abstract void readMapEnd() throws TException;

  public abstract TList readListBegin() throws TException;

  public abstract void readListEnd() throws TException;

  public abstract TSet readSetBegin() throws TException;

  public abstract void readSetEnd() throws TException;

  public abstract boolean readBool() throws TException;

  public abstract byte readByte() throws TException;

  public abstract short readI16() throws TException;

  public abstract int readI32() throws TException;

  public abstract long readI64() throws TException;

  public abstract double readDouble() throws TException;

  public abstract String readString() throws TException;

  public abstract ByteBuffer readBinary() throws TException;

thrift框架支持一下协议:

1)TBinaryProtocol :二进制格式

 2)TCompactProtocol:压缩格式 

 3)TJSONProtocol:Json格式 

 4)TSimpleJSONProtocol:提供json只写协议

这些具体的协议中都定义了一个工厂。这些工厂都实现了TProtocolFactory这个接口,这个接口中有一个方法,就是获取具体的协议的

public interface TProtocolFactory extends Serializable {
  public TProtocol getProtocol(TTransport trans);
}
依TBinaryProtocol为例,看看怎样从工厂中获取具体的协议的

 public TProtocol getProtocol(TTransport trans) {
      //首先创建一个TBinaryProtocol二进制协议对象
      TBinaryProtocol proto = new TBinaryProtocol(trans, strictRead_, strictWrite_);
      if (readLength_ != 0) {
        proto.setReadLength(readLength_);
      }
      return proto;
    }





  

猜你喜欢

转载自blog.csdn.net/shaotianqiang/article/details/27484191