方法:从源码编译安装
1.安装依赖:
sudo apt-get update
sudo apt-get install git automake bison flex g++ libboost-all-dev libevent-dev libssl-dev libtool make pkg-config
2.下载 Thrift 源码:
你可以从 Apache Thrift 的官方网站下载源码,或者使用 Git 克隆源码仓库。
git clone https://github.com/apache/thrift.git
cd thrift
3.生成配置文件:
./bootstrap.sh
4.配置:
./configure
如果你想指定安装路径,可以使用 --prefix
选项,例如:
./configure --prefix=/usr/local --with-cmake
5.编译和安装:
make
sudo make install
6.验证安装:
运行以下命令来验证 Thrift 是否安装成功:
thrift --version
使用Thrift框架:
步骤 1:定义 Thrift 接口
首先,创建一个 .thrift
文件来定义你的服务接口。例如,创建一个名为 calculator.thrift
的文件:
namespace cpp calculator
service Calculator
{
i32 add(1: i32 num1, 2: i32 num2),
i32 subtract(1: i32 num1, 2: i32 num2),
}
步骤 2:使用 Thrift 编译器生成代码
使用 Thrift 编译器生成客户端和服务器端代码。假设你要生成 C++ 代码:
thrift --gen cpp calculator.thrift
这将在当前目录下生成一个 gen-cpp
文件夹,其中包含生成的代码。
步骤 3:编写服务器端代码
在生成的代码基础上,编写服务器端代码。例如,创建一个名为 CalculatorServer.cpp
的文件:
#include "gen-cpp/Calculator.h"
#include <thrift/transport/TServerSocket.h>
#include <thrift/transport/TBufferTransports.h>
#include <thrift/protocol/TBinaryProtocol.h>
#include <thrift/server/TSimpleServer.h>
using namespace ::apache::thrift;
using namespace ::apache::thrift::protocol;
using namespace ::apache::thrift::transport;
using namespace ::apache::thrift::server;
using namespace calculator;
class CalculatorHandler : public CalculatorIf
{
public:
CalculatorHandler() {}
int32_t add(const int32_t num1, const int32_t num2) override
{
return num1 + num2;
}
int32_t subtract(const int32_t num1, const int32_t num2) override
{
return num1 - num2;
}
};
int main()
{
int port = 9090;
::std::shared_ptr<CalculatorHandler> handler(new CalculatorHandler());
::std::shared_ptr<TProcessor> processor(new CalculatorProcessor(handler));
::std::shared_ptr<TServerTransport> serverTransport(new TServerSocket(port));
::std::shared_ptr<TTransportFactory> transportFactory(new TBufferedTransportFactory());
::std::shared_ptr<TProtocolFactory> protocolFactory(new TBinaryProtocolFactory());
TSimpleServer server(processor, serverTransport, transportFactory, protocolFactory);
server.serve();
return 0;
}
步骤 4:编写客户端代码
同样地,编写客户端代码。例如,创建一个名为 CalculatorClient.cpp
的文件:
#include "gen-cpp/Calculator.h"
#include <thrift/transport/TSocket.h>
#include <thrift/transport/TTransportUtils.h>
#include <thrift/protocol/TBinaryProtocol.h>
#include <iostream>
#include <cstdlib> // for std::atoi
using namespace ::apache::thrift;
using namespace ::apache::thrift::protocol;
using namespace ::apache::thrift::transport;
using namespace calculator;
int main(int argc, char** argv)
{
if (argc != 3)
{
std::cerr << "Usage: " << argv[0] << " <num1> <num2>" << std::endl;
return 1;
}
int num1 = std::atoi(argv[1]);
int num2 = std::atoi(argv[2]);
::std::shared_ptr<TTransport> socket(new TSocket("localhost", 9090));
::std::shared_ptr<TTransport> transport(new TBufferedTransport(socket));
::std::shared_ptr<TProtocol> protocol(new TBinaryProtocol(transport));
CalculatorClient client(protocol);
try
{
transport->open();
int32_t sum = client.add(num1, num2);
std::cout << num1 << " + " << num2 << " = " << sum << std::endl;
transport->close();
}
catch (TException& tx)
{
std::cerr << "ERROR: " << tx.what() << std::endl;
}
return 0;
}
步骤 5:编译和运行
编译服务器和客户端代码。假设你使用 g++ 编译器:
g++ -std=c++11 -o CalculatorServer CalculatorServer.cpp gen-cpp/Calculator.cpp -L/usr/local/lib -lthrift -Wl,-rpath,/usr/local/lib
g++ -std=c++11 -o CalculatorClient CalculatorClient.cpp gen-cpp/Calculator.cpp -L/usr/local/lib -lthrift -Wl,-rpath,/usr/local/lib
运行
1.运行服务器:
./CalculatorServer
2.运行客户端:
在另一个终端窗口中运行:
./CalculatorClient
Thrift框架实现网络通信:
整体项目目录结构如下:
ThriftExample/
├── CMakeLists.txt
├── cmake/
│ └── FindThrift.cmake
├── student.thrift
├── src/
│ ├── StudentServer.cpp
│ ├── StudentClient.cpp
│ └── gen-cpp/
│ ├── StudentService.cpp
│ ├── StudentService.h
│ ├── StudentService_server.skeleton.cpp
│ ├── student_types.cpp
│ ├── student_types.h
└── build/
1.student.thrift
文件如下所示:
namespace cpp student
struct Student
{
1: i32 id,
2: string name,
3: i32 grade
}
struct Response
{
1: string status,
2: i32 code
}
service StudentService
{
Response sendStudent(1: Student student)
}
2.使用 Thrift 编译器生成 C++ 代码:
thrift --gen cpp student.thrift
3.创建 CMakeLists.txt
文件:
cmake_minimum_required(VERSION 3.10)
project(ThriftExample)
# 添加 cmake 目录到 CMAKE_MODULE_PATH
set(CMAKE_MODULE_PATH ${CMAKE_MODULE_PATH} "${CMAKE_SOURCE_DIR}/cmake")
# 查找 Thrift 包
find_package(Thrift REQUIRED)
# 包含生成的 Thrift 代码目录
include_directories(${CMAKE_CURRENT_SOURCE_DIR}/src/gen-cpp)
# 包含 Thrift 头文件目录
include_directories(${THRIFT_INCLUDE_DIR})
# 生成服务器可执行文件
add_executable(StudentServer src/StudentServer.cpp src/gen-cpp/StudentService.cpp src/gen-cpp/student_types.cpp)
target_link_libraries(StudentServer ${THRIFT_LIBRARIES})
# 生成客户端可执行文件
add_executable(StudentClient src/StudentClient.cpp src/gen-cpp/StudentService.cpp src/gen-cpp/student_types.cpp)
target_link_libraries(StudentClient ${THRIFT_LIBRARIES})
4.创建 cmake/FindThrift.cmake 文件:
find_path(THRIFT_INCLUDE_DIR thrift/Thrift.h)
find_library(THRIFT_LIBRARIES NAMES thrift)
include(FindPackageHandleStandardArgs)
find_package_handle_standard_args(Thrift DEFAULT_MSG THRIFT_INCLUDE_DIR THRIFT_LIBRARIES)
mark_as_advanced(THRIFT_INCLUDE_DIR THRIFT_LIBRARIES)
5.编写服务器端代码: src/StudentServer.cpp
#include <iostream>
#include <memory>
#include <thrift/server/TSimpleServer.h>
#include <thrift/server/TThreadPoolServer.h>
#include <thrift/protocol/TBinaryProtocol.h>
#include <thrift/transport/TServerSocket.h>
#include <thrift/transport/TBufferTransports.h>
#include <thrift/transport/TTransportUtils.h>
#include "gen-cpp/StudentService.h"
using namespace std;
using namespace apache::thrift;
using namespace apache::thrift::protocol;
using namespace apache::thrift::transport;
using namespace apache::thrift::server;
using namespace student;
class StudentServiceHandler : public StudentServiceIf
{
public:
StudentServiceHandler() = default;
void sendStudent(Response& _return, const Student& student) override
{
cout << "Received student: ID=" << student.id << ", Name=" << student.name << ", Grade=" << student.grade << endl;
_return.status = "Success";
_return.code = 200;
}
};
int main()
{
int port = 9090;
shared_ptr<StudentServiceHandler> handler(new StudentServiceHandler());
shared_ptr<TProcessor> processor(new StudentServiceProcessor(handler));
shared_ptr<TServerTransport> serverTransport(new TServerSocket(port));
shared_ptr<TTransportFactory> transportFactory(new TBufferedTransportFactory());
shared_ptr<TProtocolFactory> protocolFactory(new TBinaryProtocolFactory());
TSimpleServer server(processor, serverTransport, transportFactory, protocolFactory);
cout << "Starting the server..." << endl;
server.serve();
return 0;
}
6.编写客户端代码: src/StudentClient.cpp
#include <iostream>
#include <memory> // 使用标准库的 shared_ptr
#include <thrift/transport/TSocket.h>
#include <thrift/transport/TBufferTransports.h>
#include <thrift/protocol/TBinaryProtocol.h>
#include "gen-cpp/StudentService.h"
using namespace std;
using namespace apache::thrift;
using namespace apache::thrift::protocol;
using namespace apache::thrift::transport;
using namespace student;
int main()
{
std::shared_ptr<TTransport> socket(new TSocket("localhost", 9090));
std::shared_ptr<TTransport> transport(new TBufferedTransport(socket));
std::shared_ptr<TProtocol> protocol(new TBinaryProtocol(transport));
StudentServiceClient client(protocol);
try
{
transport->open();
Student student;
student.id = 1;
student.name = "John Doe";
student.grade = 95;
Response response;
client.sendStudent(response, student);
cout << "Response: Status=" << response.status << ", Code=" << response.code << endl;
transport->close();
}
catch (TException& tx)
{
cout << "ERROR: " << tx.what() << endl;
}
return 0;
}
7.编译和运行:
在build目录下执行下列指令
cmake ..
make