CでのThriftの使用

あいさつ、愛するhabrayuzer。



少し背景から始めましょう。 現時点では、サーバー部分(いくつかのサービスを含む)と特定のプラットフォームに移植されたクライアントSDKで構成されるかなり複雑な製品に取り組んでいます。 この動物園全体を何らかの方法で一緒にテストする必要があります。



適切なSDKを使用するクライアントアプリケーション(ドライバーの種類)が作成され、「サーバーにアクセスして、これを行う」、「検証のためにそのような結果を提供する」などのテストサービスからコマンドを受け取ることができます。 クライアントは、 Thriftwiki )を使用してコマンドを受け取ります。 そして、SDKをCに移植し、ApacheがCの適切なマニュアルを持っていないことが判明するまで、すべてが順調でした 同じ場所で、このマニュアルを作成するためのチケットとわずかな例を見つけました。 CでのThriftの使用が成功した後、このトピックに関する小さな教育プログラムを作成することが決定されました。



私たちが設定した目標:

-クライアントは、Thriftを使用してテストサービスからコマンドを受信する必要があります。

-チームは優れていますが、サーバーと通信する必要もあります。

-クライアントは1つのスレッドで動作する必要があります。



Apache Webサイトの「RPC計算機」の例を使用して、作業の機能について説明します。 Thriftの優れた実装ではglibを使用しているため、必要になります。

まず、例のスキームに従ってソースコードを生成します。



thrift -r --gen c_glib ./tutorial.thrift







いくつかの* .cおよび* .hファイルを取得しました。 今後必要になります。

次に、Thrift接続を初期化する関数を作成します。



Thrift_init()関数
 #include <glib.h> #include <glib-object.h> #include <thrift/c_glib/protocol/thrift_protocol.h> #include <thrift/c_glib/protocol/thrift_binary_protocol.h> #include <thrift/c_glib/transport/thrift_transport.h> #include <thrift/c_glib/transport/thrift_buffered_transport.h> #include <thrift/c_glib/transport/thrift_socket.h> #include <unistd.h> #include <stdlib.h> #include <stdio.h> #include <calculator.h> //   static ThriftSocket *socket = NULL; static ThriftTransport *transport = NULL; static ThriftProtocol *protocol = NULL; static CalculatorClient *client = NULL; static CalculatorIf *iface = NULL; int thrift_init(const char *hostname, int port) { printf("Initializing Thrift client (server=%s:%d)...\n", hostname, port); g_type_init(); GError *error = NULL; socket = THRIFT_SOCKET(g_object_new(THRIFT_TYPE_SOCKET, "hostname", hostname, "port", port, &error)); if (error) { printf("Failed to create thrift socket: %s\n", error->message); g_error_free(error); return -1; } transport = THRIFT_TRANSPORT(g_object_new(THRIFT_TYPE_BUFFERED_TRANSPORT, "transport", socket, &error)); if (error) { printf("Failed to create thrift transport: %s\n", error->message); g_error_free(error); return -1; } protocol = THRIFT_PROTOCOL(g_object_new(THRIFT_TYPE_BINARY_PROTOCOL, "transport", transport, &error)); if (error) { printf("Failed to create thrift binary protocol: %s\n", error->message); g_error_free(error); return -1; } client = CALCULATOR_CLIENT(g_object_new(TYPE_CALCULATOR_CLIENT, "input_protocol", protocol, "output_protocol", protocol, &error)); if (error) { printf("Failed to create thrift client: %s\n", error->message); g_error_free(error); return -1; } iface = CALCULATOR_IF(client); thrift_transport_open(transport, &error); //   if (error) { printf("Failed to open thrift connection: %s\n", error->message); g_error_free(error); return -1; } return socket->sd; //   .   }
      
      







ここでは、データ転送用のソケット、トランスポートバイナリプロトコル、クライアントインターフェイスなどのような重要なものを作成して初期化します。次に、計算機メソッドの呼び出しを試みます。



 GError *error = NULL; gint32 result = 0; calculator_client_add(iface, &result, 4, 3, &error);
      
      







結果変数で値7を取得しましたが、これでは十分ではありません。 呼び出しがブロックされていることが判明しました。この場合、テストサービスはコマンド/結果をすぐに返さない可能性がありますが、クライアントはまだサーバーからの応答を読み取って処理する必要があります(1つのスレッドで作業していることを覚えていますか?) 幸いなことに、Thriftの実装により、 calculator_client_addへの呼び出しを2つの呼び出し( calculator_client_send_addcalculator_client_recv_add)に分割できます 。 最初のものは、関数引数を使用してリクエストを送信します。 2番目はそれぞれ、返された値で応答を読み取ります。 関数thrift_initは、ソケットのThriftハンドルを返すだけなので、それを使用します。



 int main() { int socket = -1; if ((socket = thrift_init("localhost", 9090)) >= 0) { GError *error = NULL; calculator_client_send_add(iface, 4, 3, &error); if (error) { //   g_error_free(error); return -1; } struct pollfd fds; fds.fd = socket; fds.events = POLLIN; fds.revents = 0; if (poll(&fds, 1, 5000 /*5  */) > 0) { if (fds.revents & POLLIN) { gint32 result = 0; calculator_client_recv_add(iface, &result, &error); //  7  result if (error) { //   g_error_free(error); return -1; } } } return 0; } return -1; }
      
      







そして最後に-リソースを解放する関数:



Thrift_destroy()関数
 void thrift_destroy() { if (transport) { thrift_transport_close(transport, NULL); g_object_unref(transport); } if (client) { g_object_unref(client); } if (protocol) { g_object_unref(protocol); } if (socket) { g_object_unref(socket); } }
      
      





したがって、私たちはなんとか1つの石で2羽の鳥を殺すことができました。サーバーと通信し、th約の呼びかけを引くためです。 この場合、フォークとスレッドはありません。 Thriftは素晴らしい、使いやすいRPCツールです。Cで開発している場合でも。



All Articles