Ubuntu 16.04 原始碼安裝Thrift的過程記錄
1、首先需要安裝依賴的軟體包 ,參考網址官方安裝說明
sudo apt-get install automake bison flex g++ git libboost-all-dev libevent-dev libssl-dev libtool make pkg-config
2、建立一個目錄,用git下載原始碼或者到網站下載最新的穩定版原始碼包下載地址
git clone https://github.com/apache/thrift.git
cd thrift
3、執行安裝步驟,簡化為 一下幾部分,如果不是通過git下載的,則不需要執行bootstrap.sh,參考
./bootstrap.sh
./configure
make
sudo make install
4、進行測試,編寫exchange.thrift檔案,檔案內容如下
#!/usr/local/bin/thrift --gen cpp
namespace cpp Test
namespace java com.thrift.test
service NucInfoExchange {
string execute(1:string instruction)
void push(1:string message)
}
5、生成C++和Java程式碼
thrift --gen cpp exchange.thrift thrift --gen java exchange.thrift
這兩行命令將會在當前目錄下生成gen-cpp和gen-java兩個目錄,這兩個目錄裡面就是生成的C++和java程式碼
6、首先進入gen-cpp目錄,將生成的NucInfoExchange_server.skeleton.cpp拷貝為NucInfoExchange_server.cpp,並修改程式碼,執行如下命令
cd gen-cpp
cp NucInfoExchange_server.skeleton.cpp NucInfoExchange_server.cpp
gedit NucInfoExchange_server.cpp
由於我主要想測試ThreadPool模式,所以對程式碼進行了修改,主要是加入了Processor的克隆類,修改了main函式,程式碼如下
// This autogenerated skeleton file illustrates how to build a server.
// You should copy it to another filename to avoid overwriting it.
#include "NucInfoExchange.h"
#include <thrift/concurrency/PlatformThreadFactory.h>
#include <thrift/transport/TSocket.h>
#include <thrift/transport/TTransportUtils.h>
#include <thrift/TToString.h>
#include <thrift/stdcxx.h>
#include <thrift/protocol/TBinaryProtocol.h>
#include <thrift/server/TSimpleServer.h>
#include <thrift/transport/TServerSocket.h>
#include <thrift/transport/TBufferTransports.h>
#include <thrift/concurrency/ThreadManager.h>
#include <thrift/concurrency/PosixThreadFactory.h>
#include <thrift/server/TThreadPoolServer.h>
#include <thrift/server/TThreadedServer.h>
#include <iostream>
#include <stdexcept>
#include <sstream>
using namespace std;
using namespace ::apache::thrift;
using namespace ::apache::thrift::protocol;
using namespace ::apache::thrift::transport;
using namespace ::apache::thrift::server;
using namespace ::apache::thrift::concurrency;
using namespace Test;
class NucInfoExchangeHandler : virtual public NucInfoExchangeIf {
public:
NucInfoExchangeHandler() {
// Your initialization goes here
}
void execute(std::string& _return, const std::string& instruction) {
// Your implementation goes here
printf("execute\n");
}
void push(const std::string& message) {
// Your implementation goes here
printf("push\n");
}
};
class NucInfoExchangeCloneFactory : virtual public NucInfoExchangeIfFactory {
public:
virtual ~NucInfoExchangeCloneFactory() {}
virtual NucInfoExchangeIf* 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 NucInfoExchangeHandler;
}
virtual void releaseHandler( NucInfoExchangeIf* handler) {
delete handler;
}
};
int main(int argc, char **argv) {
/* int port = 9898;
::apache::thrift::stdcxx::shared_ptr<NucInfoExchangeHandler> handler(new NucInfoExchangeHandler());
::apache::thrift::stdcxx::shared_ptr<TProcessor> processor(new NucInfoExchangeProcessor(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);
*/
const int workerCount = 4;
::apache::thrift::stdcxx::shared_ptr<ThreadManager> threadManager = ThreadManager::newSimpleThreadManager(workerCount);
threadManager->threadFactory(stdcxx::make_shared<PosixThreadFactory>());
threadManager->start();
TThreadPoolServer server(
stdcxx::make_shared<NucInfoExchangeProcessorFactory>(stdcxx::make_shared<NucInfoExchangeCloneFactory>()),
stdcxx::make_shared<TServerSocket>(9898),
stdcxx::make_shared<TBufferedTransportFactory>(),
stdcxx::make_shared<TBinaryProtocolFactory>(),
threadManager);
server.serve();
return 0;
}
7、開始編譯,編寫Makefile檔案如下
GEN_SRC := NucInfoExchange.cpp exchange_constants.cpp exchange_types.cpp
GEN_OBJ := $(patsubst %.cpp,%.o, $(GEN_SRC))
THRIFT_DIR := /usr/local/include/thrift
BOOST_DIR := /usr/include/boost
INC := -I$(THRIFT_DIR) -I$(BOOST_DIR)
.PHONY: all clean
all: NucInfoExchange_server
%.o: %.cpp
$(CXX) -Wall -O2 -DHAVE_INTTYPES_H -DHAVE_NETINET_IN_H $(INC) -c $< -o [email protected]
NucInfoExchange_server: NucInfoExchange_server.o $(GEN_OBJ)
$(CXX) $^ -o [email protected] -L/usr/local/lib -lthrift
clean:
$(RM) *.o NucInfoExchange_server
執行make命令,編譯沒有問題,出現了怪異的連結錯誤如下
g++ -Wall -O2 -DHAVE_INTTYPES_H -DHAVE_NETINET_IN_H -I/usr/local/include/thrift -I/usr/include/boost -c NucInfoExchange_server.cpp -o NucInfoExchange_server.o
g++ -Wall -O2 -DHAVE_INTTYPES_H -DHAVE_NETINET_IN_H -I/usr/local/include/thrift -I/usr/include/boost -c NucInfoExchange.cpp -o NucInfoExchange.o
g++ -Wall -O2 -DHAVE_INTTYPES_H -DHAVE_NETINET_IN_H -I/usr/local/include/thrift -I/usr/include/boost -c exchange_constants.cpp -o exchange_constants.o
g++ -Wall -O2 -DHAVE_INTTYPES_H -DHAVE_NETINET_IN_H -I/usr/local/include/thrift -I/usr/include/boost -c exchange_types.cpp -o exchange_types.o
g++ NucInfoExchange_server.o NucInfoExchange.o exchange_constants.o exchange_types.o -o NucInfoExchange_server -L/usr/local/lib -lthrift
NucInfoExchange_server.o:在函式‘main’中:
NucInfoExchange_server.cpp:(.text.startup+0x1e9):對‘apache::thrift::server::TThreadPoolServer::TThreadPoolServer(boost::shared_ptr<apache::thrift::TProcessorFactory> const&, boost::shared_ptr<apache::thrift::transport::TServerTransport> const&, boost::shared_ptr<apache::thrift::transport::TTransportFactory> const&, boost::shared_ptr<apache::thrift::protocol::TProtocolFactory> const&, boost::shared_ptr<apache::thrift::concurrency::ThreadManager> const&)’未定義的引用
collect2: error: ld returned 1 exit status
Makefile:17: recipe for target 'NucInfoExchange_server' failed
make: *** [NucInfoExchange_server] Error 1
看錯誤是連結的時候找不到ThreadPoolServer類,不能啊,這個肯定有,難道是用git下載的版本太高了?刪除了所有的thrift檔案,在官網上又下載了最新的穩定版thrift-0.11.0.tar.gz ,解壓編譯後,繼續編譯這個例子,依然是同樣的錯誤,折騰的都快精神崩潰了,又仔細看了看錯誤,為啥用的全都是boost::shared_ptr呢,印象中編譯時候顯示的是std=C++11 啊,靈機一動,趕緊修改Makefile檔案如下
GEN_SRC := NucInfoExchange.cpp exchange_constants.cpp exchange_types.cpp
GEN_OBJ := $(patsubst %.cpp,%.o, $(GEN_SRC))
THRIFT_DIR := /usr/local/include/thrift
BOOST_DIR := /usr/include/boost
INC := -I$(THRIFT_DIR) -I$(BOOST_DIR)
.PHONY: all clean
all: NucInfoExchange_server
%.o: %.cpp
$(CXX) -Wall -std=c++11 -O2 -DHAVE_INTTYPES_H -DHAVE_NETINET_IN_H $(INC) -c $< -o [email protected]
NucInfoExchange_server: NucInfoExchange_server.o $(GEN_OBJ)
$(CXX) $^ -o [email protected] -L/usr/local/lib -lthrift
clean:
$(RM) *.o NucInfoExchange_server
大家仔細看,編譯時增加了一個 -std=c++11選項,趕緊執行make嘗試一下,OK,成功了
8、在另外一臺windows上寫個java測試的客戶端吧,測試程式碼如下
package com.thrift.test;
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;
import org.apache.thrift.transport.TTransportException;
public class TestThrift {
public static void main(String[] args) {
System.out.println("客戶端啟動....");
for(int i = 0; i < 100 ; i++){
TestThread ts = new TestThread();
Thread thread = new Thread(ts);
thread.start();
try {
Thread.sleep(10);
} catch (InterruptedException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
}
}
class TestThread implements Runnable{
public void run() {
TTransport transport = null;
try {
transport = new TSocket("192.168.1.105", 9898, 30000);
// 協議要和服務端一致
TProtocol protocol = new TBinaryProtocol(transport);
NucInfoExchange.Client client = new NucInfoExchange.Client(protocol);
transport.open();
String result = client.execute("哈哈!!!!");
System.out.println(result);
} catch (TTransportException e) {
e.printStackTrace();
} catch (TException e) {
e.printStackTrace();
} finally {
if (null != transport) {
transport.close();
}
}
}
}
9、終於大功告成了,折騰了大半天的時間,終於搞定了,baidu和bing都用了,沒有找到任何線索,所以趕緊記錄下來,免得日後忘記了,很不容易。希望也能幫到別人。