IDL如下:
namespace java com.app.thrift.test service Hello{ UserMessage tell(1:UserMessage message) } struct UserMessage{ 1:i32 userId; 2:string username; 3:string message }
使用thrift-0.10.0.exe 生成相关的java类:
thrift-0.10.0.exe -gen java Hello.thrift
测试客户端代码:
TTransport transport = null; try { transport = new TSocket(SERVER_IP, SERVER_PORT, TIMEOUT); TProtocol protocol = new TBinaryProtocol(transport); com.app.thrift.test.hello.Hello.Client client = new Hello.Client(protocol); UserMessage message = new UserMessage(); message.setMessage(" are you come from sy?"); message.setUserId(1002); message.setUsername("user1"); transport.open(); UserMessage backMessage = client.tell(message); System.out.println("Thrify client result : " ); System.out.println("from " + backMessage.getUsername() + "(" + backMessage.getUserId() + "):" + backMessage.getMessage()); } catch (TTransportException e) { e.printStackTrace(); } catch (TException e) { e.printStackTrace(); } finally { if (null != transport) { transport.close(); } }
服务端代码只是截取报文:
try { ServerSocket serverSocket = new ServerSocket(SERVER_PORT); Socket socket = serverSocket.accept(); InputStream is = socket.getInputStream(); byte [] data = new byte[1024]; int length = is.read(data); FileOutputStream fos = new FileOutputStream(new File("c:\\test.log")); while(length>0){ fos.write(data,0,length); length = is.read(data); } fos.close(); System.out.println("readFinish"); }catch (Exception e){ e.printStackTrace(); }
数据由TProtocol写入。
TProtocol--协议层(按照协议规定的格式)--》写入--》TTransport--(代表了与另一端服务连接的通道,可如Socket)
(TProtocol 需要内部持有TTransport)
TProtocol 代码如下:
public abstract class TProtocol { /** * Transport */ protected TTransport trans_; /** * Writing methods. */ 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; /** * Reading methods. */ 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; }
得到报文(c:\\test.log),用二进制方式查看:
解释一下上图中的传输报文内容:(由TBinaryProtocol写入)
1.80 01 00 01
协议版本号 80 01 00 00 (或操作) 消息类型 01 call
消息类型为:01 对应 call--调用
其它消息类型为:
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; }
2. 00 00 00 04
方法名称长度,int型:4个bit ,值=4,即之后的4个字节为方法名称
3.74 65 6c 6c
方法名称内容: 长度由2决度 ,内容为tell
4. 00 00 00 01
方法顺序号,值1 =第一个(只有一个)
以上对应TBinaryProtocol方法:
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); } }
之后的字节描述参数:
5. 0c 00 01
第一个字节代表 类型 0C=struct
后两个字节代表 序号 00 01 :第一个struct
public void writeFieldBegin(TField field) throws TException { writeByte(field.type);//1个字节的类型 writeI16(field.id);//2个字节的顺序号 }
6. 08 00 01
第一个字节代表 类型 08= i32 整型
后两个字节代表 序号 00 01 :struct 中第一个元素
public void writeFieldBegin(TField field) throws TException { writeByte(field.type);//1个字节的元素类型 writeI16(field.id);//2个字节的元素顺序号 }7.00 00 03 ea
上面指定了元素类型为 i32,即元素内容占用4个节,这是I32类型元素内容,值十进制==1002
public void writeI32(int i32) throws TException { inoutTemp[0] = (byte)(0xff & (i32 >> 24)); inoutTemp[1] = (byte)(0xff & (i32 >> 16)); inoutTemp[2] = (byte)(0xff & (i32 >> 8)); inoutTemp[3] = (byte)(0xff & (i32)); trans_.write(inoutTemp, 0, 4); }
8.0b 00 02
第一个字节代表类型 0b=string 类型
第二个字节代表顺序号 00 02 == struct 中第二个元素
public void writeFieldBegin(TField field) throws TException { writeByte(field.type); writeI16(field.id); }
9.00 00 00 05
上面指定了第二个元素是string ,此处指定了string的长度是5,即之后的5个字节是第二个元素的内容
10.75 73 65 72 31
第二个元素的内容:user1
9与10 代码:
public void writeString(String str) throws TException { try { byte[] dat = str.getBytes("UTF-8"); writeI32(dat.length); trans_.write(dat, 0, dat.length); } catch (UnsupportedEncodingException uex) { throw new TException("JVM DOES NOT SUPPORT UTF-8"); } }
.......其它字节与上面类似,不再解释。