thrift demo
1 thrift 环境搭建
Windows thrift 下载
thrift 各版本下载链接
使用thrift -gen 生成代码
demo.thrift文件内容:
namespace java demo.thrift
service demo{
string helloString(1:string para)
}
将下载的thrift-0.14.1.exe 文件放置在一文件夹中,将编写好的demo.thrift文件放置在同一路径。
执行生成代码命令
.\thrift-0.14.1.exe -gen java .\demo.thrift
会在当前路径下生成一个gen-java目录,里面有demo.java文件。
2 编写代码
java中使用thrift,依赖相关的jar包。使用IDEA创建maven工程,引入Thrift包。
pom.xml文件内容:
<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
<modelVersion>4.0.0</modelVersion>
<groupId>org.example</groupId>
<artifactId>ThriftDemo</artifactId>
<version>1.0-SNAPSHOT</version>
<properties>
<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
<maven.compiler.source>1.8</maven.compiler.source>
<maven.compiler.target>1.8</maven.compiler.target>
<maven.compiler.compilerVersion>1.8</maven.compiler.compilerVersion>
</properties>
<dependencies>
<!-- https://mvnrepository.com/artifact/org.apache.thrift/libthrift -->
<dependency>
<groupId>org.apache.thrift</groupId>
<artifactId>libthrift</artifactId>
<version>0.13.0</version>
</dependency>
</dependencies>
</project>
将生成的demo.java文件放置在/src/main/java目录下。
另外编写 demoImpl.java、Server.java、Client.java文件。
在demoImpl.java中编写服务逻辑,示例代码如下:
import org.apache.thrift.TException;
public class DemoImpl implements demo.Iface {
@Override
public String helloString(String username) throws TException {
return "Hello " + username;
}
}
在Server.java中编写服务端程序:
import hello.DemoImpl;
import hello.demo;
import org.apache.thrift.protocol.TBinaryProtocol;
import org.apache.thrift.server.TServer;
import org.apache.thrift.server.TSimpleServer;
import org.apache.thrift.transport.TServerSocket;
import java.net.ServerSocket;
public class SimpleServer {
public static void main(String[] args) throws Exception {
ServerSocket serverSocket = new ServerSocket(9003);
TServerSocket serverTransport = new TServerSocket(serverSocket);
demo.Processor processor =
new demo.Processor<demo.Iface>(new DemoImpl());
TBinaryProtocol.Factory protocolFactory = new TBinaryProtocol.Factory();
TSimpleServer.Args tArgs = new TSimpleServer.Args(serverTransport);
tArgs.processor(processor);
tArgs.protocolFactory(protocolFactory);
// 简单的单线程服务模型 一般用于测试
TServer tServer = new TSimpleServer(tArgs);
System.out.println("Running Simple Server");
tServer.serve();
}
}
在Client.java中编写客户端程序:
import hello.demo;
import org.apache.thrift.TException;
import org.apache.thrift.protocol.TBinaryProtocol;
import org.apache.thrift.protocol.TProtocol;
import org.apache.thrift.transport.TSocket;
import org.apache.thrift.transport.TTransport;
public class SimpleClient {
public static void main(String[] args) {
TTransport transport = null;
try {
transport = new TSocket("localhost", 9003);
TProtocol protocol = new TBinaryProtocol(transport);
demo.Client client = new demo.Client(protocol);
transport.open();
String result = client.helloString("world");
System.out.println("Result =: " + result);
} catch (TException e) {
e.printStackTrace();
} finally {
if (null != transport) {
transport.close();
}
}
}
}
3 运行
首先将server端代码运行起来,然后执行客户端。
客户端正常打印:
Result =: Hello world
4 抓包分析
抓包工具wireshak安装
wireshark官方下载链接
抓包工具使用
step1 选择使用的接口,点击start
step2 输入过滤规则,点击过滤
tcp && (tcp.srcport == 9003 || tcp.dstport == 9003) # 监控tcp协议9003端口数据
step3 启动服务端,启动客户端
step4 二进制协议解析
消息类型:
类型 | 二进制 | 十进制 |
---|---|---|
Call | 001 | 1 |
Reply | 010 | 2 |
Exception | 011 | 3 |
Oneway | 100 | 4 |
数据类型:
类型 | 十进制 |
---|---|
STOP | 0 |
VOID | 1 |
BOOL | 2 |
BYTE | 3 |
DOUBLE | 4 |
I16 | 6 |
I32 | 8 |
I64 | 10 |
STRING | 11 |
STRUCT | 12 |
MAP | 13 |
SET | 14 |
LIST | 15 |
ENUM | 16 |
TCP协议传输的数据(payload):
8001 0001 0000000b 68656c6c6f537472696e67 00000001 0b 0001 00000004 7a6c7373 00
字段 | 说明 |
---|---|
8001 | 协议版本号 |
0001 | 前8位按照协议规定未被使用,后8位中的最后三位指定消息类型 |
0000000b | 消息类型后面的32位数据定义了服务名称的长度 |
68656C6C6F537472696E67 | utf-8解码:helloString |
00000001 | seq id,在其之后传输的就是具体数据 |
0b | 数据解析时,默认先读取一个字节,确定数据类型 |
0001 | 两个字节的编号,指明这段数据在结构体中的位置 |
00000004 | 如果是String类型,在其后4个字节给出Sting的长度 |
7a6c7373 | utf-8解码:zlss |
00 | 表示Stop,结束位 |