thrift 下载网址: http://archive.apache.org/dist/thrift/0.9.3/
需要下载的依赖库有:openssl-1.0.2o-- 、thrift-0.9.3、libevent-2.1.8-stable、boost_1_66_0--其中依赖库也需要生成LIB来进行调用。
1.编译BOOST: 编译好后,自己用一下 ,可以写一个简单的demo
关于boost的编译,参见 https://blog.youkuaiyun.com/ljt350740378/article/details/87091133
2.编译openssl-1.0.2o : 编译好后,自己用一下 ,可以写一个简单的demo
参见 https://blog.youkuaiyun.com/ljt350740378/article/details/87807544
2.编译 libevent-2.1.8-stable: 编译好后,自己用一下 ,可以写一个简单的demo
编译 libevent-2.1.8-stable,其中可以把 openssl嵌套编译进去,如下图:参见 https://blog.youkuaiyun.com/ljt350740378/article/details/87856875
3.下载thrift
http://thrift.apache.org/download thrift-0.12.0.tar.gz 和 thrift-0.12.0.exe
E:\canDel\thrift-0.12.0\tutorial\cpp 里面有例子教程
参考 https://github.com/Zuolijia/thrift
https://blog.youkuaiyun.com/zuolj/article/details/77450108
4.编译thrift
打开工程,如下所示: E:\canDel\thrift-0.12.0\lib\cpp\thrift.sln
thrift命令:
thrift --gen cpp xxx.thrift #Linux下
thrift-0.9.3.exe --gen cpp xxx.thrift #Windows下
thrift-0.9.3.exe -r -strict --gen cpp:cob_style xxx.thrift #异步
然后其中:添加包含目录: $(ProjectDir)\src\;$(ProjectDir)\src\thrift\windows\;E:\canDel\boost_1_59_0\;E:\canDel\libevent-2.1.9-beta\openssl\inc32\include;E:\canDel\libevent-2.1.9-beta\;E:\canDel\libevent-2.1.9-beta\include;E:\canDel\libevent-2.1.9-beta\WIN32-Code\nmake\;$(IncludePath)
库目录:$(VC_LibraryPath_x64);$(WindowsSDK_LibraryPath_x64);E:\canDel\libevent-2.1.9-beta;E:\canDel\libevent-2.1.9-beta\openssl\inc32\lib;
附加依赖库:libevent.lib;libevent_core.lib;libevent_extras.lib;libevent_openssl.lib;libeay32.lib;ssleay32.lib;
将E:\canDel\thrift-0.12.0\config.h 放入 E:\canDel\thrift-0.12.0\lib\cpp\src\thrift 中。
有时候 会出现错误,如:错误 1 error C1083: 无法打开包括文件: “netinet/in.h”: No such file or directory E:\canDel\thrift-0.12.0\lib\cpp\src\thrift\Thrift.h 32 1 libthrift
类似这样的错误,把相对就的宏在 config.h 中注释起来即可。
编译:生成: E:\canDel\thrift-0.12.0\lib\cpp\x64\Release\libthriftnb.lib E:\canDel\thrift-0.12.0\lib\cpp\x64\Release\libthrift.lib
5.调用thrift:
调用:
Hello.thrift 文件内容如下:
/*namespace cpp HelloThrift.Interface
service HelloService{
string HelloString(1:string para)
i32 HelloInt(1:i32 para)
bool HelloBoolean(1:bool para)
void HelloVoid()
string HelloNull()
}
*/
/*
struct ReResult
{
1:i16 iReMessageType,
2:string strReMessageData,
}
service HelloService
{
ReResult DataTransfer(1:i16 iMessageType, 2:string strMessageData);
}
*/
service HelloService
{
i16 addxy(1:i16 x, 2:i16 y);
}
命令如下:E:\canDel\thrift-0.12.0\lib\cpp\x64\Release>E:\canDel\thrift-0.12.0\lib\cpp\x64\Release\thrift-0.12.0.exe --gen cpp Hello.thrift
生成的文件如下 :
其中,HelloService_server.skeleton.cpp 为生成的server的代码,直接拿过来用,并在里面写上实现代码就可以。
使用的工程添加 的包含目录 为:$(VC_IncludePath);$(WindowsSDK_IncludePath);E:\canDel\thrift-0.12.0\lib\cpp\src;E:\canDel\boost_1_59_0\;
库目录 为:$(VC_LibraryPath_x64);$(WindowsSDK_LibraryPath_x64);E:\canDel\thrift-0.12.0\lib\cpp\x64\Release;D:\boost\boost_1_59_0\bin\vc12-x64\lib;
依赖的LIB为:libthrift.lib;libthriftnb.lib;libboost_thread-vc120-mt-1_59.lib;
下面编写调用thrift代码:
server方面:HelloService_server.skeleton.cpp直接拿过来用,里面有main,直接用,添加所有gen-cpp下的7个文件到server的文件夹下面,并更改 HelloService_server.skeleton.cpp 为 server.cpp 代码如下:
server.cpp:
// This autogenerated skeleton file illustrates how to build a server.
// You should copy it to another filename to avoid overwriting it.
#if 0
#include "HelloService.h"
#include <thrift/transport/TBufferTransports.h>
#include <thrift/concurrency/ThreadManager.h>
#include <thrift/concurrency/PlatformThreadFactory.h>
#include <thrift/protocol/TBinaryProtocol.h>
#include <thrift/server/TSimpleServer.h>
#include <thrift/server/TThreadPoolServer.h>
#include <thrift/server/TThreadedServer.h>
#include <thrift/transport/TServerSocket.h>
#include <thrift/transport/TSocket.h>
#include <thrift/transport/TTransportUtils.h>
#include <thrift/TToString.h>
#include <thrift/stdcxx.h>
#include <iostream>
#include <stdexcept>
#include <sstream>
//using namespace ::apache::thrift;
//using namespace ::apache::thrift::protocol;
//using namespace ::apache::thrift::transport;
//using namespace ::apache::thrift::server;
//
//using boost::shared_ptr;
//
//using namespace ::HelloThrift::Interface;
using namespace std;
using namespace apache::thrift;
using namespace apache::thrift::concurrency;
using namespace apache::thrift::protocol;
using namespace apache::thrift::transport;
using namespace apache::thrift::server;
//using namespace tutorial;
//using namespace shared;
//using namespace ::HelloThrift::Interface;
using namespace HelloThrift;
using namespace HelloThrift::Interface;;
class HelloServiceHandler : virtual public HelloServiceIf {
public:
HelloServiceHandler() {
// Your initialization goes here
}
void HelloString(std::string& _return, const std::string& para) {
// Your implementation goes here
printf("HelloString,I got your name %s\n",para.c_str());
_return = "give you back";
}
int32_t HelloInt(const int32_t para) {
// Your implementation goes here
printf("HelloInt\n");
return para;
}
bool HelloBoolean(const bool para) {
// Your implementation goes here
printf("HelloBoolean\n");
return para;
}
void HelloVoid() {
// Your implementation goes here
printf("HelloVoid\n");
}
void HelloNull(std::string& _return) {
// Your implementation goes here
printf("HelloNull\n");
}
};
int main(int argc, char **argv) {
int port = 9090;
shared_ptr<HelloServiceHandler> handler(new HelloServiceHandler());
shared_ptr<TProcessor> processor(new HelloServiceProcessor(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);
server.serve();
return 0;
}
#endif
#include "HelloService.h"
#include <thrift/protocol/TBinaryProtocol.h>
#include <thrift/server/TSimpleServer.h>
#include <thrift/transport/TServerSocket.h>
#include <thrift/transport/TBufferTransports.h>
using namespace ::apache::thrift;
using namespace ::apache::thrift::protocol;
using namespace ::apache::thrift::transport;
using namespace ::apache::thrift::server;
class HelloServiceHandler : virtual public HelloServiceIf {
public:
HelloServiceHandler() {
// Your initialization goes here
}
int16_t addxy(const int16_t x, const int16_t y) {
// Your implementation goes here
return x + y;
printf("addxy\n");
}
};
int main(int argc, char **argv)
{
printf("hello i am server\n");
int port = 9090;
::apache::thrift::stdcxx::shared_ptr<HelloServiceHandler> handler(new HelloServiceHandler());
::apache::thrift::stdcxx::shared_ptr<TProcessor> processor(new HelloServiceProcessor(handler));
::apache::thrift::stdcxx::shared_ptr<TServerTransport> serverTransport(new TServerSocket(port));
::apache::thrift::stdcxx::shared_ptr<TTransportFactory> transportFactory(new TBufferedTransportFactory());
::apache::thrift::stdcxx::shared_ptr<TProtocolFactory> protocolFactory(new TBinaryProtocolFactory());
TSimpleServer server(processor, serverTransport, transportFactory, protocolFactory);
server.serve();
return 0;
}
其中client一样,只是需要自己写client.cpp,图如下:
client.cpp代码如下:
#include "HelloService.h"
#include <thrift/concurrency/ThreadManager.h>
#include <thrift/concurrency/PlatformThreadFactory.h>
#include <thrift/protocol/TBinaryProtocol.h>
#include <thrift/server/TSimpleServer.h>
#include <thrift/server/TThreadPoolServer.h>
#include <thrift/server/TThreadedServer.h>
#include <thrift/transport/TServerSocket.h>
#include <thrift/transport/TSocket.h>
#include <thrift/transport/TTransportUtils.h>
#include <thrift/TToString.h>
#include <thrift/stdcxx.h>
#include <iostream>
#include <stdexcept>
#include <sstream>
#include <stdint.h>
using namespace std;
using namespace apache::thrift;
using namespace apache::thrift::concurrency;
using namespace apache::thrift::protocol;
using namespace apache::thrift::transport;
using namespace apache::thrift::server;
using boost::shared_ptr;
int main(int argc, char** argv)
{
stdcxx::shared_ptr<TTransport> socket(new TSocket("localhost", 9090));
stdcxx::shared_ptr<TTransport> transport(new TBufferedTransport(socket));
stdcxx::shared_ptr<TProtocol> protocol(new TBinaryProtocol(transport));
HelloServiceClient client(protocol);
try
{
transport->open();
int16_t x = 8;
int16_t y = 87;
int16_t ret = client.addxy(x, y);
printf("testClient11111 %d\n", ret);
getchar();
transport->close();
}
catch (TException& tx)
{
printf("ERROR:%s\n", tx.what());
}
}
E:\canDel\thrift-0.12.0\tutorial\cpp\CppServer.cpp中有多种server的工作模式,运行会有不同的效果,CppServer.cpp如下所示:
/*
* Licensed to the Apache Software Foundation (ASF) under one
* or more contributor license agreements. See the NOTICE file
* distributed with this work for additional information
* regarding copyright ownership. The ASF licenses this file
* to you under the Apache License, Version 2.0 (the
* "License"); you may not use this file except in compliance
* with the License. You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing,
* software distributed under the License is distributed on an
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
* KIND, either express or implied. See the License for the
* specific language governing permissions and limitations
* under the License.
*/
#include <thrift/concurrency/ThreadManager.h>
#include <thrift/concurrency/PlatformThreadFactory.h>
#include <thrift/protocol/TBinaryProtocol.h>
#include <thrift/server/TSimpleServer.h>
#include <thrift/server/TThreadPoolServer.h>
#include <thrift/server/TThreadedServer.h>
#include <thrift/transport/TServerSocket.h>
#include <thrift/transport/TSocket.h>
#include <thrift/transport/TTransportUtils.h>
#include <thrift/TToString.h>
#include <thrift/stdcxx.h>
#include <iostream>
#include <stdexcept>
#include <sstream>
#include "../gen-cpp/Calculator.h"
using namespace std;
using namespace apache::thrift;
using namespace apache::thrift::concurrency;
using namespace apache::thrift::protocol;
using namespace apache::thrift::transport;
using namespace apache::thrift::server;
using namespace tutorial;
using namespace shared;
class CalculatorHandler : public CalculatorIf {
public:
CalculatorHandler() {}
void ping() { cout << "ping()" << endl; }
int32_t add(const int32_t n1, const int32_t n2) {
cout << "add(" << n1 << ", " << n2 << ")" << endl;
return n1 + n2;
}
int32_t calculate(const int32_t logid, const Work& work) {
cout << "calculate(" << logid << ", " << work << ")" << endl;
int32_t val;
switch (work.op) {
case Operation::ADD:
val = work.num1 + work.num2;
break;
case Operation::SUBTRACT:
val = work.num1 - work.num2;
break;
case Operation::MULTIPLY:
val = work.num1 * work.num2;
break;
case Operation::DIVIDE:
if (work.num2 == 0) {
InvalidOperation io;
io.whatOp = work.op;
io.why = "Cannot divide by 0";
throw io;
}
val = work.num1 / work.num2;
break;
default:
InvalidOperation io;
io.whatOp = work.op;
io.why = "Invalid Operation";
throw io;
}
SharedStruct ss;
ss.key = logid;
ss.value = to_string(val);
log[logid] = ss;
return val;
}
void getStruct(SharedStruct& ret, const int32_t logid) {
cout << "getStruct(" << logid << ")" << endl;
ret = log[logid];
}
void zip() { cout << "zip()" << endl; }
protected:
map<int32_t, SharedStruct> log;
};
/*
CalculatorIfFactory is code generated.
CalculatorCloneFactory is useful for getting access to the server side of the
transport. It is also useful for making per-connection state. Without this
CloneFactory, all connections will end up sharing the same handler instance.
*/
class CalculatorCloneFactory : virtual public CalculatorIfFactory {
public:
virtual ~CalculatorCloneFactory() {}
virtual CalculatorIf* getHandler(const ::apache::thrift::TConnectionInfo& connInfo)
{
stdcxx::shared_ptr<TSocket> sock = stdcxx::dynamic_pointer_cast<TSocket>(connInfo.transport);
cout << "Incoming connection\n";
cout << "\tSocketInfo: " << sock->getSocketInfo() << "\n";
cout << "\tPeerHost: " << sock->getPeerHost() << "\n";
cout << "\tPeerAddress: " << sock->getPeerAddress() << "\n";
cout << "\tPeerPort: " << sock->getPeerPort() << "\n";
return new CalculatorHandler;
}
virtual void releaseHandler( ::shared::SharedServiceIf* handler) {
delete handler;
}
};
int main() {
TThreadedServer server(
stdcxx::make_shared<CalculatorProcessorFactory>(stdcxx::make_shared<CalculatorCloneFactory>()),
stdcxx::make_shared<TServerSocket>(9090), //port
stdcxx::make_shared<TBufferedTransportFactory>(),
stdcxx::make_shared<TBinaryProtocolFactory>());
/*
// if you don't need per-connection state, do the following instead
TThreadedServer server(
stdcxx::make_shared<CalculatorProcessor>(stdcxx::make_shared<CalculatorHandler>()),
stdcxx::make_shared<TServerSocket>(9090), //port
stdcxx::make_shared<TBufferedTransportFactory>(),
stdcxx::make_shared<TBinaryProtocolFactory>());
*/
/**
* Here are some alternate server types...
// This server only allows one connection at a time, but spawns no threads
TSimpleServer server(
stdcxx::make_shared<CalculatorProcessor>(stdcxx::make_shared<CalculatorHandler>()),
stdcxx::make_shared<TServerSocket>(9090),
stdcxx::make_shared<TBufferedTransportFactory>(),
stdcxx::make_shared<TBinaryProtocolFactory>());
const int workerCount = 4;
stdcxx::shared_ptr<ThreadManager> threadManager =
ThreadManager::newSimpleThreadManager(workerCount);
threadManager->threadFactory(
stdcxx::make_shared<PlatformThreadFactory>());
threadManager->start();
// This server allows "workerCount" connection at a time, and reuses threads
TThreadPoolServer server(
stdcxx::make_shared<CalculatorProcessorFactory>(stdcxx::make_shared<CalculatorCloneFactory>()),
stdcxx::make_shared<TServerSocket>(9090),
stdcxx::make_shared<TBufferedTransportFactory>(),
stdcxx::make_shared<TBinaryProtocolFactory>(),
threadManager);
*/
cout << "Starting the server..." << endl;
server.serve();
cout << "Done." << endl;
return 0;
}
运行时,先运行server,再运行client.OK.如果有两个client,server只能响应一个client,如果把其中一个关了,就会响应后面的。
后来又新建了一个client2工程,但是没有调用成功。下面查看原因--没有调用异步模式参考:https://blog.youkuaiyun.com/whycold/article/details/11019967
https://blog.youkuaiyun.com/u201012980/article/details/51867864