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