Published on

Apache Thrift を使う 5 - C++ Nonblocking Server

Authors

今日は C++ で Nonblocking Server を構築してみます.

昨日まで使用していた TSimpleServer は Blocking Server です.Blocking Server とはその名の通り,処理をリクエストしたときに処理が完了するまでクライアント側に制御が戻りません.

そういう処理で問題ないなら別にいいのですが, 一度に複数のリクエストを処理したいとか,すぐにクライアント側で別の処理を したいとかあると思います.むしろそういう方が多いですかね?

まずはサーバーサイド,追加の include と main を少し変更します.newSimpleThreadManager に渡している数字は一度に処理できる リクエスト数です.libthriftnb,libevent のリンクをお忘れなく.Windows の Python は Nonblocking Server に対応していなかった気がします.

#define HAVE_CONFIG_H

#include "gen-cpp/Calculator.h"
#include <thrift/protocol/TBinaryProtocol.h>
#include <thrift/server/TSimpleServer.h>
#include <thrift/transport/TServerSocket.h>
#include <thrift/transport/TBufferTransports.h>
#include <concurrency/ThreadManager.h>
#include <concurrency/BoostThreadFactory.h>
#include <server/TNonblockingServer.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;

using namespace ::calc;

class CalculatorHandler : virtual public CalculatorIf {
 public:
  CalculatorHandler() {
    // Your initialization goes here
  }

  double plus(const double arg1, const double arg2) {
    // Your implementation goes here
    printf("plusn");
 return arg1 + arg2;
  }

  double minus(const double arg1, const double arg2) {
    // Your implementation goes here
    printf("minusn");
 return arg1 - arg2;
  }

  double multiplies(const double arg1, const double arg2) {
    // Your implementation goes here
    printf("multipliesn");
 return arg1 * arg2;
  }

  double divides(const double arg1, const double arg2) {
    // Your implementation goes here
    printf("dividesn");
 return arg1 / arg2;
  }

};

int main(int argc, char **argv) {

  WSADATA wsaData;
  WSAStartup(MAKEWORD(2, 0), &wsaData);

  int port = 9090;
  shared_ptr handler(new CalculatorHandler());
  shared_ptr processor(new CalculatorProcessor(handler));
  shared_ptr protocolFactory(new TBinaryProtocolFactory());
  shared_ptr threadManager = ThreadManager::newSimpleThreadManager(15);
  shared_ptr threadFactory(new BoostThreadFactory());

  threadManager->threadFactory(threadFactory);
  threadManager->start();

  TNonblockingServer server(processor, protocolFactory, port, threadManager);

  server.serve();
  return 0;
}

クライアント側はほとんど同じです.注意点としては TBufferedTransport を TFramedTransport に変更してください.これを間違えると動かなかった気がします.Python の場合も昨日のソースコードを TFramedTransport にすれば OK です.

#define HAVE_CONFIG_H

#include "gen-cpp/Calculator.h"

#include <protocol/TBinaryProtocol.h>
#include <transport/TSocket.h>
#include <transport/TTransportUtils.h>

using namespace apache::thrift;
using namespace apache::thrift::protocol;
using namespace apache::thrift::transport;
using namespace calc;

int main(int argc, char** argv) {

  boost::shared_ptr socket(new TSocket("localhost", 9090));
  boost::shared_ptr transport(new TFramedTransport(socket));
  boost::shared_ptr protocol(new TBinaryProtocol(transport));

  CalculatorClient client(protocol);

  try {
    transport->open();

    printf("2 + 3 = %fn", client.plus(2, 3));
    printf("6 - 3 = %fn", client.minus(6, 3));
    printf("8 * 3 = %fn", client.multiplies(8, 3));
    printf("16 / 5 = %fn", client.divides(16, 5));

    transport->close();
  } catch (TException& tx) {
    printf("ERROR: %sn", tx.what());
  }
  return 0;
}