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 $@

NucInfoExchange_server: NucInfoExchange_server.o $(GEN_OBJ)  
	$(CXX) $^ -o $@ -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 $@

NucInfoExchange_server: NucInfoExchange_server.o $(GEN_OBJ)  
	$(CXX) $^ -o $@ -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都用了,没有找到任何线索,所以赶紧记录下来,免得日后忘记了,很不容易。希望也能帮到别人。

猜你喜欢

转载自blog.csdn.net/jdx0909/article/details/84727523