1. 程式人生 > >Thrift c++ server / java client配置

Thrift c++ server / java client配置

在安裝thrift前需要安裝libevent,用於生成對應的lib連結。

這裡寫圖片描述

server端

Linux配置

1.下載
從官網http://thrift.apache.org/上下載thrift-0.8.0版本,之前使用的是0.9.3版本,編譯時會報錯,因而改成了0.8.0版本。

2.解壓thrift壓縮檔案

tar zxvf thrift-0.8.0.tar.gz  

3.安裝
進入到thrift-0.8.0目錄

cd thrift-0.8.0

執行

./configure --prefix=/usr/local/ --with-boost=/usr/local --without-php
make  
make install 

安裝時遇到如下錯誤

./configure --prefix=/usr/local/
thift configure: error: "Error: libcrypto required."

這個問題百度了下是缺少某些軟體導致的,但是因為虛擬機器配置問題一直上不了網,就只能依靠網上的建議手動安裝某些軟體來解決這個問題,然而安裝了很多東西還是不行,掙扎許久還是先去解決上網問題了·······

可以上網後,解決Error: libcrypto required.問題:
安裝 openssl openssl-devel (centOS)

yum -y install openssl openssl-devel
./configure --prefix=/usr/local/

執行後發現yum命令報錯:

This system is not registered with RHN

Redhat之所以會出現這個錯誤是因為沒有註冊RHN,只需要更新一下yum的源就可以了。

解決:
進入yum的配置目錄

cd /etc/yum.repos.d/

下載CentOS- Base.repo檔案

wget http://docs.linuxtone.org/soft/lemp/CentOS-Base.repo 

將原有的rhel-debuginfo.repo備份一下

cp rhel-debuginfo.repo
rhel-debuginfo2.repo

將CentOS- Base.repo重新命名成rhel-debuginfo.repo

mv CentOS-Base.repo rhel-debuginfo.repo

安裝成功

yum install build-essential

此時再次執行

./configure --prefix=/usr/local/ --with-boost=/usr/local --without-php
make  
make install

在終端輸入 thrift –version 終於安裝成功

Thrift安裝總結:之前嘗試在windows下配置c++作為伺服器端,java作為客戶端封裝thrift,但是thrift編譯後總是一執行就各種出錯,多次嘗試失敗後只好換到了linux下進行配置和安裝=_=

4.定義thrift檔案

user.thrift

struct User{  
 1: string uid,  
 2: string uname,  
 3: bool usex,  
 4: i16 uage,  
}  
service UserService{  
 void add(1: User u),  
 User get(1: string uid),  
}  

5.通過thrift的shell工具命令生成c++,java程式碼框架

Shell程式碼

thrift -r --gen cpp user.thrift     
thrift -r --gen java user.thrift  

通過執行以上命令:會生成子目錄gen-cpp,gen-java。

6.通過執行如下命令,生成C/C++服務端程式碼

Shell程式碼

cp gen-cpp/UserService_server.skeleton.cpp UserServer.cpp  

7.修改服務端的程式碼,如下所示

#include "UserService.h"  
#include <config.h>  
#include <protocol/TCompactProtocol.h>  
#include <server/TSimpleServer.h>  
#include <transport/TServerSocket.h>  
#include <transport/TBufferTransports.h>  
#include <concurrency/ThreadManager.h>  
#include <concurrency/PosixThreadFactory.h>  
#include <server/TThreadPoolServer.h>  
#include <server/TThreadedServer.h>  
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 boost::shared_ptr;  

class UserServiceHandler : virtual public UserServiceIf {  
 public:  
  UserServiceHandler() {  
  }  

  void add(const User& u) {   
    printf("uid=%s uname=%s usex=%d uage=%d\n", u.uid.c_str(), u.uname.c_str(), u.usex, u.uage);  
    if(u.uage<5)
      printf("too young");
  }  

  void get(User& _return, const std::string& uid) {  
    _return.uid = uid;  
    _return.uname = "喵";  
    _return.usex = "妹子"; 
    _return.uage = 7;  
    printf("uid=%s uname=%s usex=%d uage=%d\n", _return.uid.c_str(), _return.uname.c_str(), _return.usex, _return.uage);  
  }  

};  

int main(int argc, char **argv) {  
  shared_ptr<UserServiceHandler> handler(new UserServiceHandler());  
  shared_ptr<TProcessor> processor(new UserServiceProcessor(handler));  
  shared_ptr<TProtocolFactory> protocolFactory(new TCompactProtocolFactory());  
  shared_ptr<TTransportFactory> transportFactory(new TBufferedTransportFactory());  
  shared_ptr<TServerTransport> serverTransport(new TServerSocket(9090));  

  shared_ptr<ThreadManager> threadManager = ThreadManager::newSimpleThreadManager(10);  
  shared_ptr<PosixThreadFactory> threadFactory = shared_ptr<PosixThreadFactory>(new PosixThreadFactory());  
  threadManager->threadFactory(threadFactory);  
  threadManager->start();  
  printf("start user server...\n");  

  TThreadPoolServer server(processor, serverTransport, transportFactory, protocolFactory, threadManager);  
  server.serve();  
  return 0;  
}

這裡使用的是TCompactProtocol,則需要#include<config.h>,還有就是Blocking的多執行緒伺服器。

8.執行如下命令

g++ -g -o UserServer -I /usr/local/include/thrift  -I /usr/include/boost/  -I ./gen-cpp -L /usr/local/lib -lthrift UserServer.cpp ./gen-cpp/user_types.cpp ./gen-cpp/user_constants.cpp ./gen-cpp/UserService.cpp

剛開始執行報錯,滿滿一頁錯誤簡直喪心病狂,各種找不到檔案,因為是按照別人的教程配置的,很多安裝細節可能不一樣,最後只好根據需要把src檔案重新命名為thrift放到/usr/local/include/下,並把boost放到/usr/include/下,以及把找不到的config.h放到需要的目錄下,再次執行發現錯誤少了不少,果然是缺少檔案的原因。

但是還有報錯資訊顯示thrift自帶的包有問題,查詢報錯的位置,發現是沒有加this->引發的錯誤,加上之後伺服器端終於可以運行了,激動哭/(ㄒoㄒ)/~~

client端

Linux下客戶端配置:

執行java程式需要有jdk,發現虛擬機器上未安裝,於是使用yum安裝,一切順利,但是奇怪的是環境變數配置好後,javac命令居然找不到,到對應的路徑下發現居然真的沒有這個命令·········重新解除安裝安裝多次未果,只好用windows搜尋需要的壓縮包手動匯入了,以下為java安裝過程:

1.先解除安裝伺服器自帶的jdk軟體包

rpm -qa | grep jdk
yum -y remove 顯示的java名稱

2.從windows下載 jdk-7u67-linux-x64.tar.gz

偷個懶,直接解壓用filezilla匯入Linux下

3.移動到相應位置

mv jdk-7u67-linux-x64 /usr/lib/jvm/java7

4.新增jdk7.0到系統環境變數

cp /etc/profile /etc/profile.bak
vi /etc/profile

5.編輯新增下面的內容

export JAVA_HOME=/usr/lib/jvm/java7
export JRE_HOME=${JAVA_HOME}/jre 
export CLASSPATH=.:${JAVA_HOME}/lib:${JRE_HOME}/lib
export PATH=${JAVA_HOME}/bin:$PATH

6.儲存後在命令列輸入如下語句使配置立即生效

source /etc/profile

7.輸入如下語句判斷是否成功

java -version

客戶端java程式碼:

public static void main(String[] args) {  

  try {  
   TTransport transport;  
   String ip="x.x.x.x";
   transport = new TSocket(ip, 9090);  

   TProtocol protocol = new TBinaryProtocol(transport);  
   UserService.Client client = new UserService.Client(protocol);  
   transport.open();  

   User u = new User();
   u.uid = "001";
   u.uname="22";
   u.usex = "妹子";
   u.uage = 3;
   client.add(u);
   System.out.println("新增使用者成功了喲!");  
   transport.close();  
  } catch (TTransportException e) {  
   e.printStackTrace();  
  } catch (TException x) {  
   x.printStackTrace();  
  }  
 } 

安裝成功後我就直接把java程式簡單粗暴的複製到linux下準備執行了,直接用javac執行的main函式,發現居然找不到jar包裡面的類,同時還各種報錯,後來才知道正確的開啟方式是要打成jar包再執行,簡直傻到哭o(╥﹏╥)o。

將jar包匯入linux下並執行jar包,當然前提是伺服器已經開啟。

java -jar client.jar

注:伺服器端執行後處於監聽狀態,此時需要再開一個session開啟客戶端,之前把伺服器停掉又開客戶端發現出不來結果還很奇怪=_=,最後可以成功的開始通訊了。

客戶端:
這裡寫圖片描述
伺服器端:
這裡寫圖片描述

補充:

Windows下的客戶端終於可以用了,原來一直覺得是windows這邊的防火牆的問題,各種配置未果,後來突然想到可能是linux下的防火牆,試了一下,果然是!!終於解決了,心情都舒暢了起來~

以下是解決方法:

1.先檢視linux下的防火牆配置

iptables -L -n

發現貌似windows能訪問的服務都包含在了裡面,於是猜測可能需要把伺服器這邊的埠開啟。

2.開啟防火牆配置檔案

vi /etc/sysconfig/iptables

3.新增如下一行後並儲存

ACCEPT     tcp  --  0.0.0.0/0            0.0.0.0/0           state NEW tcp dpt:9091 

4.關閉後重新開啟防火牆

/etc/rc.d/init.d/iptables stop
/etc/rc.d/init.d/iptables start

再次使用windows下的客戶端進行訪問,發現真的成功了~好激動,撒花~✿✿ヽ(°▽°)ノ✿