<?xml version="1.0" encoding="UTF-8"?>
<rss version="2.0"
	xmlns:content="http://purl.org/rss/1.0/modules/content/"
	xmlns:wfw="http://wellformedweb.org/CommentAPI/"
	xmlns:dc="http://purl.org/dc/elements/1.1/"
	xmlns:atom="http://www.w3.org/2005/Atom"
	xmlns:sy="http://purl.org/rss/1.0/modules/syndication/"
	xmlns:slash="http://purl.org/rss/1.0/modules/slash/"
	>

<channel>
	<title>Yoichi Kawasaki&#039;s Web &#187; rpc</title>
	<atom:link href="http://yk55.com/blog/tags/rpc/feed/" rel="self" type="application/rss+xml" />
	<link>http://yk55.com/blog</link>
	<description>my publicly accessible private memorandums</description>
	<lastBuildDate>Mon, 14 May 2012 01:31:02 +0000</lastBuildDate>
	<language>en</language>
	<sy:updatePeriod>hourly</sy:updatePeriod>
	<sy:updateFrequency>1</sy:updateFrequency>
	<generator>http://wordpress.org/?v=3.3.2</generator>
	<!-- google_ad_section_end --><!-- google_ad_section_start(weight=ignore) -->	<item>
		<title>LibeventのRPCフレームワークによるC/Sプログラミング</title>
		<link>http://yk55.com/blog/2010/06/05/libevent_rpc_cs_programmin/</link>
		<comments>http://yk55.com/blog/2010/06/05/libevent_rpc_cs_programmin/#comments</comments>
		<pubDate>Sat, 05 Jun 2010 14:49:21 +0000</pubDate>
		<dc:creator>yoichi</dc:creator>
				<category><![CDATA[Programming]]></category>
		<category><![CDATA[c]]></category>
		<category><![CDATA[cplusplus]]></category>
		<category><![CDATA[http]]></category>
		<category><![CDATA[libevent]]></category>
		<category><![CDATA[network]]></category>
		<category><![CDATA[rpc]]></category>

		<guid isPermaLink="false">http://yk55.com/blog/?p=361</guid>
		<description><![CDATA[前回の投稿ではlibeventのHTTP処理機能evhttpを使ったHTTPサーバを紹介したが今回はlibeventのRPCフレームワーク evrpcを使ったC/Sプログラミング方法を紹介してみる。このevrpcはかなりマイナーな部類のフレームワークといえる。これに関するドキュメントは少なく、検索してみるとまともなページがヒットしない。ヘッダやテストコードを読まない人にとってはちょっと厳しいかもしれない。 巷にはハイパフォーマンスで使いやすく少し検索すれば豊富なドキュメントやブログ記事がわさわさと出てくるようなフレームワークがごろごろしているのでこんなに地味で愛想ないフレームワークをふつーは選ばない。 そんな人気のないevrpcだけど実際に使ってみると思ったより悪くない。 動作は安定しているしAPIはシンプルで使いやすく拡張性も考慮されていてHook関数、Callback関数を駆使すれば好きに振る舞いを制御することができる。 少々粗挽きなところは全く気にしないでこれをベースに自分なりに使いやすいフレームワークを作ってやろうくらいに思ってる人には向いているかもしれない。 RPC marshalling用コードのジェネレート &#8211; event_rpcgen.py marshallingとはRPC C/S処理で内部的に使用するデータ構造をネットワーク転送用のフォーマットに変換することで、その逆をdemarshallingと呼ぶ。厳密には意味が違うらしいがserializationとdeserializationみたいなもの。 libeventにはデータ構造をmarshalling、demarshallingするコードをジェネレートするためのスクリプトが用意されている。それがevent_rpcgen.py。RPC C/S処理で使用するデータ構造を定められたフォーマットで定義してやりそれをevent_rpcgen.pyに食わせてやることでコードが生成される。 データ構造の定義フォーマットは次のとおり。 [データ構造の定義フォーマット] struct &#60;data struct name&#62; { &#160; &#160; [optional] &#60;type&#62; &#60;varname&#62; = &#60;index&#62;; &#160; &#160; &#160;... } &#60;type&#62; データ型 &#160; - string &#160;文字列 &#160; - bytes &#160;uint_tベクター。 [lenght]で長さを指定。　例、bytes hoge[10] &#160; - int &#160;uint32_t &#160; - struct[structname] &#160;構造体 &#160; - array [...]]]></description>
			<content:encoded><![CDATA[<p><a href="http://yk55.com/blog/2010/04/30/eventdriven_http_server_vs_httpd/">前回の投稿</a>では<a href="http://www.monkey.org/~provos/libevent/">libevent</a>のHTTP処理機能<a href="http://www.monkey.org/~provos/libevent/doxygen-1.4.10/evhttp_8h.html">evhttp</a>を使ったHTTPサーバを紹介したが今回はlibeventのRPCフレームワーク <a href="http://www.monkey.org/~provos/libevent/doxygen-1.4.10/evrpc_8h.html">evrpc</a>を使ったC/Sプログラミング方法を紹介してみる。このevrpcはかなりマイナーな部類のフレームワークといえる。これに関するドキュメントは少なく、検索してみるとまともなページがヒットしない。ヘッダやテストコードを読まない人にとってはちょっと厳しいかもしれない。 巷にはハイパフォーマンスで使いやすく少し検索すれば豊富なドキュメントやブログ記事がわさわさと出てくるようなフレームワークがごろごろしているのでこんなに地味で愛想ないフレームワークをふつーは選ばない。 そんな人気のないevrpcだけど実際に使ってみると思ったより悪くない。 動作は安定しているしAPIはシンプルで使いやすく拡張性も考慮されていてHook関数、Callback関数を駆使すれば好きに振る舞いを制御することができる。 少々粗挽きなところは全く気にしないでこれをベースに自分なりに使いやすいフレームワークを作ってやろうくらいに思ってる人には向いているかもしれない。</p>
<p><h2><strong>RPC marshalling用コードのジェネレート &#8211; event_rpcgen.py</strong></h2>
<p><a href="http://en.wikipedia.org/wiki/Marshalling_%28computer_science%29">marshalling</a>とはRPC C/S処理で内部的に使用するデータ構造をネットワーク転送用のフォーマットに変換することで、その逆をdemarshallingと呼ぶ。厳密には意味が違うらしいがserializationとdeserializationみたいなもの。 libeventにはデータ構造をmarshalling、demarshallingするコードをジェネレートするためのスクリプトが用意されている。それが<a href="http://levent.git.sourceforge.net/git/gitweb.cgi?p=levent/levent;a=blob;f=event_rpcgen.py;h=05f0a3622aa7d9343d8f3e86f6c42fc0465e46ae;hb=HEAD">event_rpcgen.py</a>。RPC C/S処理で使用するデータ構造を定められたフォーマットで定義してやりそれをevent_rpcgen.pyに食わせてやることでコードが生成される。 データ構造の定義フォーマットは次のとおり。</p>
<div class="codecolorer-container text mac-classic" style="overflow:auto;white-space:nowrap;border:1px solid #9F9F9F;"><div class="text codecolorer" style="padding:5px;font:normal 12px/1.4em Monaco, Lucida Console, monospace;white-space:nowrap">[データ構造の定義フォーマット]<br />
<br />
struct &lt;data struct name&gt; {<br />
&nbsp; &nbsp; [optional] &lt;type&gt; &lt;varname&gt; = &lt;index&gt;;<br />
&nbsp; &nbsp; &nbsp;...<br />
}<br />
<br />
&lt;type&gt; データ型<br />
&nbsp; - string &nbsp;文字列<br />
&nbsp; - bytes &nbsp;uint_tベクター。 [lenght]で長さを指定。　例、bytes hoge[10]<br />
&nbsp; - int &nbsp;uint32_t<br />
&nbsp; - struct[structname] &nbsp;構造体<br />
&nbsp; - array &lt;type&gt; &nbsp;typeで指定されたデータ型のベクター。 typeはstring, bytes, int, または struct[structname]<br />
<br />
&lt;varname&gt; 変数名<br />
&lt;index&gt; インデックス番号。フィールド番号。<br />
<br />
[optional] &nbsp;typeの前にoptionalを指定するとリクエスト、レスポンス処理時にそのフィールドへのデータセットを省略することができる。<br />
<br />
※ &nbsp;定義ファイルの拡張子は.rpcである必要がある<br />
※ &nbsp;&lt;varname&gt; と&lt;index&gt;の間は１半角スペースずつを開ける。 そうでない場合はevent_rpcgen.pyによるジェネレートが失敗するので要注意！<br />
&nbsp; &nbsp;× &nbsp; &nbsp;int errcode =1;<br />
&nbsp; &nbsp;× &nbsp; &nbsp;int errcode &nbsp; = 1;<br />
&nbsp; &nbsp;× &nbsp; &nbsp;int errcode=1;<br />
&nbsp; &nbsp;○ &nbsp; &nbsp;int errcode = 1</div></div>
<p>今回のサンプルで使用するデータ構造を定義する。 サンプルはユーザ情報を取得するRPCでありユーザ情報取得のためのリクエスト、レスポンス用データ構造が以下のGetUserRequest、GetUserResponse。</p>
<p><u>サンプルデータ構造の定義フォーマットファイル &#8211; <A href="http://github.com/yokawasa/any/blob/master/libevent_rpc/simple.rpc">simple.rpc</A></u></p>
<div class="codecolorer-container c mac-classic" style="overflow:auto;white-space:nowrap;border:1px solid #9F9F9F;"><div class="c codecolorer" style="padding:5px;font:normal 12px/1.4em Monaco, Lucida Console, monospace;white-space:nowrap"><span style="color: #993333;">struct</span> GetUserRequest <span style="color: #009900;">&#123;</span><br />
&nbsp; &nbsp; string id <span style="color: #339933;">=</span> <span style="color: #0000dd;">1</span><span style="color: #339933;">;</span><br />
<span style="color: #009900;">&#125;</span><br />
<br />
<span style="color: #993333;">struct</span> GetUserResponse <span style="color: #009900;">&#123;</span><br />
&nbsp; &nbsp; <span style="color: #993333;">int</span> errcode <span style="color: #339933;">=</span> <span style="color: #0000dd;">1</span><span style="color: #339933;">;</span><br />
&nbsp; &nbsp; optional string name <span style="color: #339933;">=</span> <span style="color: #0000dd;">2</span><span style="color: #339933;">;</span><br />
&nbsp; &nbsp; optional string email <span style="color: #339933;">=</span> <span style="color: #0000dd;">3</span><span style="color: #339933;">;</span><br />
<span style="color: #009900;">&#125;</span></div></div>
<p>これを次のようにevent_rpcgen.pyを使ってデータ構造定義からコードをジェネレートする。 event_rpcgen.pyはlibeventをインストールするとデフォルトで/usr/local/bin/配下にコピーされる。</p>
<div class="codecolorer-container text mac-classic" style="overflow:auto;white-space:nowrap;border:1px solid #9F9F9F;"><div class="text codecolorer" style="padding:5px;font:normal 12px/1.4em Monaco, Lucida Console, monospace;white-space:nowrap">$ /usr/local/bin/event_rpcgen.py simple.rpc<br />
<br />
Reading &quot;./simple.rpc&quot;<br />
&nbsp; Created struct: GetUserRequest<br />
&nbsp; &nbsp; Added entry: id<br />
&nbsp; Created struct: GetUserResponse<br />
&nbsp; &nbsp; Added entry: errcode<br />
&nbsp; &nbsp; Added entry: name<br />
&nbsp; &nbsp; Added entry: email<br />
... creating &quot;./simple.gen.h&quot;<br />
... creating &quot;./simple.gen.c&quot;</div></div>
<p><a href="http://github.com/yokawasa/any/blob/master/libevent_rpc/simple.gen.h">simple.gen.h</a>と<a href="http://github.com/yokawasa/any/blob/master/libevent_rpc/simple.gen.c">simple.gen.c</a>の2つのファイルがジェネレートされる。 C/S両方でこのデータ構造を使用する。</p>
<p><h2><strong>RPCサーバの実装 &#8211; simple_rpc_server.cpp</strong></h2>
<p><a href="http://github.com/yokawasa/any/blob/master/libevent_rpc/simple_rpc_server.cpp">http://github.com/yokawasa/any/blob/master/libevent_rpc/simple_rpc_server.cpp</a></p>
<p>まずは利用するRPCメソッドの登録を行う。 <a href="http://www.monkey.org/~provos/libevent/doxygen-1.4.10/evrpc_8h.html#a526799df545537b2dc67358b0dfaa15">EVRPC_HEADER</a>でRPCコマンドのデータ構造とプロトタイプを作成して<a href="http://www.monkey.org/~provos/libevent/doxygen-1.4.10/evrpc_8h.html#f7abcafae087e3c4dce6a4cd85346114">EVRPC＿GENERATE</a>でRPCメッセージを送受信するためのコードを作成する。</p>
<div class="codecolorer-container c mac-classic" style="overflow:auto;white-space:nowrap;border:1px solid #9F9F9F;"><div class="c codecolorer" style="padding:5px;font:normal 12px/1.4em Monaco, Lucida Console, monospace;white-space:nowrap"><span style="color: #339933;">#ifdef __cplusplus</span><br />
<span style="color: #000000; font-weight: bold;">extern</span> <span style="color: #ff0000;">&quot;C&quot;</span> <span style="color: #009900;">&#123;</span><br />
<span style="color: #339933;">#endif</span><br />
<span style="color: #339933;">#include &quot;simple.gen.h&quot;</span><br />
<span style="color: #339933;">#ifdef __cplusplus</span><br />
<span style="color: #009900;">&#125;</span><br />
<span style="color: #339933;">#endif</span><br />
<span style="color: #339933;">#include &quot;evrpc.h&quot;</span><br />
&nbsp; &nbsp; <br />
<span style="color: #808080; font-style: italic;">/* registe RPC : GetUser */</span><br />
EVRPC_HEADER<span style="color: #009900;">&#40;</span>GetUser<span style="color: #339933;">,</span> GetUserRequest<span style="color: #339933;">,</span> GetUserResponse<span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span><br />
<span style="color: #808080; font-style: italic;">/* generate RPC code : GetUser */</span><br />
EVRPC_GENERATE<span style="color: #009900;">&#40;</span>GetUser<span style="color: #339933;">,</span> GetUserRequest<span style="color: #339933;">,</span> GetUserResponse<span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span></div></div>
<p>RPCサーバの実装について説明する。実装は既に存在するHTTPサーバの実装をベースとする。RPCサーバの基本コードは以下の通り。</p>
<div class="codecolorer-container c mac-classic" style="overflow:auto;white-space:nowrap;border:1px solid #9F9F9F;"><div class="c codecolorer" style="padding:5px;font:normal 12px/1.4em Monaco, Lucida Console, monospace;white-space:nowrap"><span style="color: #993333;">int</span> main<span style="color: #009900;">&#40;</span><span style="color: #993333;">int</span> argc<span style="color: #339933;">,</span> <span style="color: #993333;">char</span> <span style="color: #339933;">**</span>argv<span style="color: #009900;">&#41;</span> <span style="color: #009900;">&#123;</span><br />
&nbsp; &nbsp; <span style="color: #b1b100;">if</span> <span style="color: #009900;">&#40;</span>argc <span style="color: #339933;">&lt;</span> <span style="color: #0000dd;">3</span><span style="color: #009900;">&#41;</span> <span style="color: #009900;">&#123;</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; <a href="http://www.opengroup.org/onlinepubs/009695399/functions/fprintf.html"><span style="color: #000066;">fprintf</span></a><span style="color: #009900;">&#40;</span>stdout<span style="color: #339933;">,</span> <span style="color: #ff0000;">&quot;%s &lt;server&gt; &lt;port&gt;<span style="color: #000099; font-weight: bold;">\n</span>&quot;</span><span style="color: #339933;">,</span> argv<span style="color: #009900;">&#91;</span><span style="color: #0000dd;">0</span><span style="color: #009900;">&#93;</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; <span style="color: #b1b100;">return</span> <span style="color: #0000dd;">1</span><span style="color: #339933;">;</span><br />
&nbsp; &nbsp; <span style="color: #009900;">&#125;</span><br />
&nbsp; &nbsp; <span style="color: #993333;">char</span> <span style="color: #339933;">*</span>svr_addr <span style="color: #339933;">=</span> argv<span style="color: #009900;">&#91;</span><span style="color: #0000dd;">1</span><span style="color: #009900;">&#93;</span><span style="color: #339933;">;</span><br />
&nbsp; &nbsp; <span style="color: #993333;">short</span> svr_port <span style="color: #339933;">=</span> <a href="http://www.opengroup.org/onlinepubs/009695399/functions/atoi.html"><span style="color: #000066;">atoi</span></a><span style="color: #009900;">&#40;</span>argv<span style="color: #009900;">&#91;</span><span style="color: #0000dd;">2</span><span style="color: #009900;">&#93;</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span><br />
<br />
&nbsp; &nbsp; <span style="color: #993333;">struct</span> evhttp <span style="color: #339933;">*</span>ev_http <span style="color: #339933;">=</span> NULL<span style="color: #339933;">;</span><br />
&nbsp; &nbsp; <span style="color: #993333;">struct</span> evrpc_base <span style="color: #339933;">*</span>rpc_base <span style="color: #339933;">=</span> NULL<span style="color: #339933;">;</span><br />
<br />
&nbsp; &nbsp; <span style="color: #808080; font-style: italic;">/* initialize base event mechanism */</span><br />
&nbsp; &nbsp; event_init<span style="color: #009900;">&#40;</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span><br />
&nbsp; &nbsp; ev_http <span style="color: #339933;">=</span> evhttp_start<span style="color: #009900;">&#40;</span>svr_addr<span style="color: #339933;">,</span> svr_port<span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span><br />
&nbsp; &nbsp; <span style="color: #808080; font-style: italic;">/* create a base for the RPC protocol */</span><br />
&nbsp; &nbsp; rpc_base <span style="color: #339933;">=</span> evrpc_init<span style="color: #009900;">&#40;</span>ev_http<span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span><br />
<br />
&nbsp; &nbsp; <span style="color: #808080; font-style: italic;">/* register all of the handlers for all RPCs */</span><br />
&nbsp; &nbsp; EVRPC_REGISTER<span style="color: #009900;">&#40;</span>rpc_base<span style="color: #339933;">,</span> GetUser<span style="color: #339933;">,</span> GetUserRequest<span style="color: #339933;">,</span> GetUserResponse<span style="color: #339933;">,</span> GetUserCallback<span style="color: #339933;">,</span> NULL<span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span><br />
<br />
&nbsp; &nbsp; <span style="color: #808080; font-style: italic;">/* loop and dispatch events */</span><br />
&nbsp; &nbsp; event_dispatch<span style="color: #009900;">&#40;</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span><br />
<br />
&nbsp; &nbsp; EVRPC_UNREGISTER<span style="color: #009900;">&#40;</span>rpc_base<span style="color: #339933;">,</span> GetUser<span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span><br />
&nbsp; &nbsp; evrpc_free<span style="color: #009900;">&#40;</span>rpc_base<span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span><br />
&nbsp; &nbsp; evhttp_free<span style="color: #009900;">&#40;</span>ev_http<span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span><br />
&nbsp; &nbsp; <span style="color: #b1b100;">return</span> <span style="color: #0000dd;">0</span><span style="color: #339933;">;</span><br />
<span style="color: #009900;">&#125;</span></div></div>
<ul>
<li>event_init()でlibeventライブラリ初期化。とりあえずlibeventを使う際は最初に一度実行しておく。</li>
<li>evhttp_start(svr_addr, svr_port)にサーバアドレス、ポートを指定してHTTPサーバ処理開始準備。</li>
<li>evrpc_init()でrpc処理ハンドル用ポインタを作成。</li>
<li><a href="http://www.monkey.org/~provos/libevent/doxygen-1.4.10/evrpc_8h.html#bb204281e2555a1e91ff3885747d0533">EVRPC_REGISTER</a>で特定のRPCコマンドをサーバに登録する。ここではさきほどEVRPC_HEADERとEVRPC_GENERATEで登録されたRPCコマンドGetUser（リクエスト用データ構造GetUserRequest, レスポンス用データ構造GetUserResponse）をRPCサーバに登録する。また同時にGetUserCallbackというRPCリクエストを受け取った際に呼び出されるコールバック関数を登録する。GetUserCallbackは次で説明する。</li>
<li>event_dispatch()でloop開始しイベントdispatchを開始する。</li>
<li>後処理。サーバ処理を終えるときEVRPC_UNREGISTER、evrpc_free, evhttp_freeの順で後処理をする。</li>
</ul>
<p><p>
GetUserCallbackはさきほどEVRPC_REGISTERでサーバに登録されたRPCコマンドのコールバック関数。 RPCクライアントから送信されるリクエストデータからidを取得。そのidに対するnameとemailデータをレスポンスデータにセットしている。</p>
<div class="codecolorer-container c mac-classic" style="overflow:auto;white-space:nowrap;border:1px solid #9F9F9F;"><div class="c codecolorer" style="padding:5px;font:normal 12px/1.4em Monaco, Lucida Console, monospace;white-space:nowrap"><span style="color: #993333;">static</span> <span style="color: #993333;">void</span><br />
GetUserCallback<span style="color: #009900;">&#40;</span>EVRPC_STRUCT<span style="color: #009900;">&#40;</span>GetUser<span style="color: #009900;">&#41;</span><span style="color: #339933;">*</span> rpc<span style="color: #339933;">,</span> <span style="color: #993333;">void</span> <span style="color: #339933;">*</span>arg<span style="color: #009900;">&#41;</span><br />
<span style="color: #009900;">&#123;</span><br />
&nbsp; &nbsp; <span style="color: #993333;">struct</span> GetUserRequest<span style="color: #339933;">*</span> req <span style="color: #339933;">=</span> rpc<span style="color: #339933;">-&gt;</span>request<span style="color: #339933;">;</span><br />
&nbsp; &nbsp; <span style="color: #993333;">struct</span> GetUserResponse<span style="color: #339933;">*</span> res <span style="color: #339933;">=</span> rpc<span style="color: #339933;">-&gt;</span>reply<span style="color: #339933;">;</span><br />
<br />
&nbsp; &nbsp; <span style="color: #808080; font-style: italic;">/* get request info */</span><br />
&nbsp; &nbsp; <span style="color: #993333;">char</span> <span style="color: #339933;">*</span>id<span style="color: #339933;">;</span><br />
&nbsp; &nbsp; <span style="color: #b1b100;">if</span><span style="color: #009900;">&#40;</span><span style="color: #339933;">!</span>EVTAG_HAS<span style="color: #009900;">&#40;</span>req<span style="color: #339933;">,</span> id<span style="color: #009900;">&#41;</span><span style="color: #009900;">&#41;</span> <span style="color: #009900;">&#123;</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; <a href="http://www.opengroup.org/onlinepubs/009695399/functions/fprintf.html"><span style="color: #000066;">fprintf</span></a><span style="color: #009900;">&#40;</span>stderr<span style="color: #339933;">,</span> <span style="color: #ff0000;">&quot;failed to get request info<span style="color: #000099; font-weight: bold;">\n</span>&quot;</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; EVTAG_ASSIGN<span style="color: #009900;">&#40;</span>res<span style="color: #339933;">,</span> errcode<span style="color: #339933;">,</span> <span style="color: #339933;">-</span><span style="color: #0000dd;">1</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span><br />
&nbsp; &nbsp; <span style="color: #009900;">&#125;</span><br />
&nbsp; &nbsp; EVTAG_GET<span style="color: #009900;">&#40;</span>req<span style="color: #339933;">,</span> id<span style="color: #339933;">,</span> <span style="color: #339933;">&amp;</span>id<span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span><br />
&nbsp; &nbsp; <a href="http://www.opengroup.org/onlinepubs/009695399/functions/fprintf.html"><span style="color: #000066;">fprintf</span></a><span style="color: #009900;">&#40;</span>stdout<span style="color: #339933;">,</span> <span style="color: #ff0000;">&quot;REQUEST id = %s<span style="color: #000099; font-weight: bold;">\n</span>&quot;</span><span style="color: #339933;">,</span> id<span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span><br />
<br />
&nbsp; &nbsp; <span style="color: #808080; font-style: italic;">/* do somthing due to request info */</span><br />
&nbsp; &nbsp; <span style="color: #808080; font-style: italic;">/* set response info */</span><br />
&nbsp; &nbsp; EVTAG_ASSIGN<span style="color: #009900;">&#40;</span>res<span style="color: #339933;">,</span> errcode<span style="color: #339933;">,</span> <span style="color: #0000dd;">0</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span><br />
&nbsp; &nbsp; EVTAG_ASSIGN<span style="color: #009900;">&#40;</span>res<span style="color: #339933;">,</span> name<span style="color: #339933;">,</span> <span style="color: #ff0000;">&quot;Fooo Baaar&quot;</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span><br />
&nbsp; &nbsp; EVTAG_ASSIGN<span style="color: #009900;">&#40;</span>res<span style="color: #339933;">,</span> email<span style="color: #339933;">,</span> <span style="color: #ff0000;">&quot;baz@foo.bar&quot;</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span><br />
<br />
&nbsp; &nbsp; <span style="color: #808080; font-style: italic;">/* send the reply to the RPC */</span><br />
&nbsp; &nbsp; EVRPC_REQUEST_DONE<span style="color: #009900;">&#40;</span>rpc<span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span><br />
<span style="color: #009900;">&#125;</span></div></div>
<ul>
<li>EVTAG_HASでリクエストデータ構造中のあるフィールドにデータがセットされているかをチェック(ここではid)してEVTAG_GETで実際にそのフィールドデータを取得。</li>
<li>EVTAG_ASSIGNでレスポンスデータ構造のフィールド(ここではerrcode, name, email)にデータをセット。</li>
<li>EVRPC_REQUEST_DONEでレスポンス送信。</li>
</ul>
<p><h2><strong>RPCクライアントの実装 &#8211; simple_rpc_client.cpp</strong></h2>
<p><a href="http://github.com/yokawasa/any/blob/master/libevent_rpc/simple_rpc_client.cpp">http://github.com/yokawasa/any/blob/master/libevent_rpc/simple_rpc_client.cpp<br />
</a><br />
RPCクライアントの実装について説明する。RPCクライアントでもサーバと同じようにEVRPC_HEADERとEVRPC＿GENERATEとで利用するRPCメソッドの登録を行う。以下RPCクライアントの基本コード。</p>
<div class="codecolorer-container c mac-classic" style="overflow:auto;white-space:nowrap;border:1px solid #9F9F9F;"><div class="c codecolorer" style="padding:5px;font:normal 12px/1.4em Monaco, Lucida Console, monospace;white-space:nowrap"><span style="color: #993333;">int</span> main<span style="color: #009900;">&#40;</span><span style="color: #993333;">int</span> argc<span style="color: #339933;">,</span> <span style="color: #993333;">char</span> <span style="color: #339933;">**</span>argv<span style="color: #009900;">&#41;</span> <span style="color: #009900;">&#123;</span><br />
&nbsp; &nbsp; <span style="color: #b1b100;">if</span> <span style="color: #009900;">&#40;</span>argc <span style="color: #339933;">&lt;</span> <span style="color: #0000dd;">3</span><span style="color: #009900;">&#41;</span> <span style="color: #009900;">&#123;</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; <a href="http://www.opengroup.org/onlinepubs/009695399/functions/fprintf.html"><span style="color: #000066;">fprintf</span></a><span style="color: #009900;">&#40;</span>stdout<span style="color: #339933;">,</span> <span style="color: #ff0000;">&quot;%s &lt;server&gt; &lt;port&gt;<span style="color: #000099; font-weight: bold;">\n</span>&quot;</span><span style="color: #339933;">,</span> argv<span style="color: #009900;">&#91;</span><span style="color: #0000dd;">0</span><span style="color: #009900;">&#93;</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; <span style="color: #b1b100;">return</span> <span style="color: #0000dd;">1</span><span style="color: #339933;">;</span><br />
&nbsp; &nbsp; <span style="color: #009900;">&#125;</span><br />
&nbsp; &nbsp; <span style="color: #993333;">char</span> <span style="color: #339933;">*</span>svr_addr <span style="color: #339933;">=</span> argv<span style="color: #009900;">&#91;</span><span style="color: #0000dd;">1</span><span style="color: #009900;">&#93;</span><span style="color: #339933;">;</span><br />
&nbsp; &nbsp; <span style="color: #993333;">short</span> svr_port <span style="color: #339933;">=</span> <a href="http://www.opengroup.org/onlinepubs/009695399/functions/atoi.html"><span style="color: #000066;">atoi</span></a><span style="color: #009900;">&#40;</span>argv<span style="color: #009900;">&#91;</span><span style="color: #0000dd;">2</span><span style="color: #009900;">&#93;</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span><br />
&nbsp; &nbsp; <span style="color: #993333;">struct</span> event_base <span style="color: #339933;">*</span>ev_base <span style="color: #339933;">=</span> NULL<span style="color: #339933;">;</span><br />
&nbsp; &nbsp; <span style="color: #993333;">struct</span> evhttp <span style="color: #339933;">*</span>ev_http <span style="color: #339933;">=</span> NULL<span style="color: #339933;">;</span><br />
&nbsp; &nbsp; <span style="color: #993333;">struct</span> evrpc_base <span style="color: #339933;">*</span>rpc_base <span style="color: #339933;">=</span> NULL<span style="color: #339933;">;</span><br />
&nbsp; &nbsp; <span style="color: #993333;">struct</span> evrpc_pool <span style="color: #339933;">*</span>rpc_pool <span style="color: #339933;">=</span> NULL<span style="color: #339933;">;</span><br />
&nbsp; &nbsp; <span style="color: #993333;">struct</span> GetUserRequest <span style="color: #339933;">*</span>req<span style="color: #339933;">;</span><br />
&nbsp; &nbsp; <span style="color: #993333;">struct</span> GetUserResponse <span style="color: #339933;">*</span>res<span style="color: #339933;">;</span><br />
<br />
&nbsp; &nbsp; <span style="color: #808080; font-style: italic;">/* initialize base event mechanism */</span><br />
&nbsp; &nbsp; ev_base <span style="color: #339933;">=</span> event_init<span style="color: #009900;">&#40;</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span><br />
&nbsp; &nbsp; <span style="color: #808080; font-style: italic;">/* initialize http internal buffer */</span><br />
&nbsp; &nbsp; ev_http <span style="color: #339933;">=</span> evhttp_new<span style="color: #009900;">&#40;</span>ev_base<span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span><br />
&nbsp; &nbsp; <span style="color: #808080; font-style: italic;">/* create a base for the RPC protocol */</span><br />
&nbsp; &nbsp; rpc_base <span style="color: #339933;">=</span> evrpc_init<span style="color: #009900;">&#40;</span>ev_http<span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span><br />
<br />
&nbsp; &nbsp; rpc_pool <span style="color: #339933;">=</span> get_rpc_pool<span style="color: #009900;">&#40;</span>ev_base<span style="color: #339933;">,</span> svr_addr<span style="color: #339933;">,</span> svr_port<span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span><br />
&nbsp; &nbsp; <span style="color: #b1b100;">if</span><span style="color: #009900;">&#40;</span><span style="color: #339933;">!</span>rpc_pool<span style="color: #009900;">&#41;</span> <span style="color: #009900;">&#123;</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; <span style="color: #b1b100;">return</span> <span style="color: #339933;">-</span><span style="color: #0000dd;">1</span><span style="color: #339933;">;</span><br />
&nbsp; &nbsp; <span style="color: #009900;">&#125;</span><br />
&nbsp; &nbsp; <span style="color: #808080; font-style: italic;">/* set up request data */</span><br />
&nbsp; &nbsp; req <span style="color: #339933;">=</span> GetUserRequest_new<span style="color: #009900;">&#40;</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span><br />
&nbsp; &nbsp; EVTAG_ASSIGN<span style="color: #009900;">&#40;</span>req<span style="color: #339933;">,</span> id<span style="color: #339933;">,</span> <span style="color: #ff0000;">&quot;foobar&quot;</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span><br />
<br />
&nbsp; &nbsp; <span style="color: #808080; font-style: italic;">/* create a response structure */</span><br />
&nbsp; &nbsp; res <span style="color: #339933;">=</span> GetUserResponse_new<span style="color: #009900;">&#40;</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span><br />
&nbsp; &nbsp; <span style="color: #808080; font-style: italic;">/* set request, response, callback func */</span><br />
&nbsp; &nbsp; EVRPC_MAKE_REQUEST<span style="color: #009900;">&#40;</span>GetUser<span style="color: #339933;">,</span> rpc_pool<span style="color: #339933;">,</span> req<span style="color: #339933;">,</span> res<span style="color: #339933;">,</span> GetUserCallback<span style="color: #339933;">,</span> NULL<span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span><br />
&nbsp; &nbsp; <span style="color: #808080; font-style: italic;">/* process request and response */</span><br />
&nbsp; &nbsp; event_dispatch<span style="color: #009900;">&#40;</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span><br />
<br />
&nbsp; &nbsp; GetUserRequest_free<span style="color: #009900;">&#40;</span>req<span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span><br />
&nbsp; &nbsp; GetUserResponse_free<span style="color: #009900;">&#40;</span>res<span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span><br />
<br />
&nbsp; &nbsp; evrpc_pool_free<span style="color: #009900;">&#40;</span>rpc_pool<span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span><br />
&nbsp; &nbsp; evrpc_free<span style="color: #009900;">&#40;</span>rpc_base<span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span><br />
&nbsp; &nbsp; evhttp_free<span style="color: #009900;">&#40;</span>ev_http<span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span><br />
&nbsp; &nbsp; <span style="color: #b1b100;">return</span> <span style="color: #0000dd;">0</span><span style="color: #339933;">;</span><br />
<span style="color: #009900;">&#125;</span></div></div>
<ul>
<li>event_init()でlibeventライブラリ初期化。</li>
<li>evhttp_new()でhttp処理用内部バッファーを初期化。</li>
<li>evrpc_init()でrpc処理ハンドル用ポインタを作成。</li>
<li>get_rpc_pool()よりevrpc_poolポインタを取得。get_rpc_pool()は次で説明。 evrpc_poolは内部にリクエストとして送信するための接続ポインタ(evhttp_connection)を持っている。</li>
<li>GetUserRequest_new()とGetUserResponse_new()によりRPCリクエストとレスポンスのためのリソース確保。</li>
<li>EVTAG_ASSIGNによりリクエスト用データ構造のidフィールドに値(&#8220;foobar&#8221;)を設定。</li>
<li><a href="http://www.monkey.org/~provos/libevent/doxygen-1.4.10/evrpc_8h.html#ff0efcd7cb8b966256b5127960bd2c81">EVRPC_MAKE_REQUEST</a>でサーバへのリクエスト送信に使うRPCコマンドとリクエスト、レスポンスオブジェクトポインタ、evrpc_poolポインタ、コールバック関数をセットする。コールバック関数GetUserCallbackは後で説明する。</li>
<li>event_dispatch()を呼んで実際にリクエスト送信、レスポンス受信を行う。</li>
<li>後処理。GetUserRequest_free()、GetUserResponse_free()でそれぞれリクエストとレスポンスのために確保されたリソースを開放。 次にevrpc_pool_free、evrpc_free, evhttp_freeの順で後処理実行。</li>
</ul>
<p><p>
RPCリクエスト処理で使用するevrpc_poolポインタを取得するための関数。get_rpc_poolがコールされる度にサーバ接続ポインタ (evhttp_connection)を生成しevrpc_poolの接続プールに追加している。 ちなみにevrpc_poolとはいわゆるコネクションプールのこと。仕組みとしては内部に接続とリクエストを管理するQUEUEを持っていてリクエストごとに接続QUEUEから空いている接続をリクエストに割り当てる。もし割り当てる接続がなければそのリクエストをリクエストQUEUEに追加する。</p>
<div class="codecolorer-container c mac-classic" style="overflow:auto;white-space:nowrap;border:1px solid #9F9F9F;"><div class="c codecolorer" style="padding:5px;font:normal 12px/1.4em Monaco, Lucida Console, monospace;white-space:nowrap"><span style="color: #993333;">static</span> <span style="color: #993333;">struct</span> evrpc_pool <span style="color: #339933;">*</span><br />
&nbsp;get_rpc_pool<span style="color: #009900;">&#40;</span><span style="color: #993333;">struct</span> event_base <span style="color: #339933;">*</span>base<span style="color: #339933;">,</span> <span style="color: #993333;">const</span> <span style="color: #993333;">char</span> <span style="color: #339933;">*</span>svr_addr<span style="color: #339933;">,</span> <span style="color: #993333;">short</span> svr_port<span style="color: #009900;">&#41;</span><br />
<span style="color: #009900;">&#123;</span><br />
&nbsp; &nbsp; <span style="color: #993333;">struct</span> evhttp_connection <span style="color: #339933;">*</span>ev_conn<span style="color: #339933;">;</span><br />
&nbsp; &nbsp; <span style="color: #993333;">struct</span> evrpc_pool <span style="color: #339933;">*</span>rpc_pool<span style="color: #339933;">;</span><br />
&nbsp; &nbsp; rpc_pool <span style="color: #339933;">=</span> evrpc_pool_new<span style="color: #009900;">&#40;</span>base<span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span><br />
&nbsp; &nbsp; <span style="color: #b1b100;">if</span> <span style="color: #009900;">&#40;</span><span style="color: #339933;">!</span>rpc_pool<span style="color: #009900;">&#41;</span> <span style="color: #009900;">&#123;</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; <a href="http://www.opengroup.org/onlinepubs/009695399/functions/fprintf.html"><span style="color: #000066;">fprintf</span></a><span style="color: #009900;">&#40;</span>stderr<span style="color: #339933;">,</span> <span style="color: #ff0000;">&quot;failed to get new rpc pool<span style="color: #000099; font-weight: bold;">\n</span>&quot;</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; <span style="color: #b1b100;">return</span> NULL<span style="color: #339933;">;</span><br />
&nbsp; &nbsp; <span style="color: #009900;">&#125;</span><br />
&nbsp; &nbsp; <span style="color: #666666; font-style: italic;">// create a connection to RPC server</span><br />
&nbsp; &nbsp; ev_conn <span style="color: #339933;">=</span> evhttp_connection_new<span style="color: #009900;">&#40;</span>svr_addr<span style="color: #339933;">,</span> svr_port<span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span><br />
&nbsp; &nbsp; <span style="color: #b1b100;">if</span> <span style="color: #009900;">&#40;</span><span style="color: #339933;">!</span>ev_conn<span style="color: #009900;">&#41;</span> <span style="color: #009900;">&#123;</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; <a href="http://www.opengroup.org/onlinepubs/009695399/functions/fprintf.html"><span style="color: #000066;">fprintf</span></a><span style="color: #009900;">&#40;</span>stderr<span style="color: #339933;">,</span> <span style="color: #ff0000;">&quot;failed to get new evhttp connection: %s:%d<span style="color: #000099; font-weight: bold;">\n</span>&quot;</span><span style="color: #339933;">,</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; svr_addr<span style="color: #339933;">,</span> svr_port<span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; <span style="color: #b1b100;">return</span> NULL<span style="color: #339933;">;</span><br />
&nbsp; &nbsp; <span style="color: #009900;">&#125;</span><br />
&nbsp; &nbsp; <span style="color: #666666; font-style: italic;">// add request connection in the pool</span><br />
&nbsp; &nbsp; evrpc_pool_add_connection<span style="color: #009900;">&#40;</span>rpc_pool<span style="color: #339933;">,</span> ev_conn<span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span><br />
&nbsp; &nbsp; <span style="color: #b1b100;">return</span> <span style="color: #009900;">&#40;</span>rpc_pool<span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span><br />
<span style="color: #009900;">&#125;</span></div></div>
<ul>
<li>evrpc_pool_new()でrpcコネクションプールを作成。</li>
<li>evhttp_connection_newでリクエスト用接続ポインタを生成。</li>
<li>evrpc_pool_add_connectionでevrpc_poolの接続プールに生成されたリクエスト用接続ポインタを追加。</li>
</ul>
<p><p>
以下EVRPC_MAKE_REQUESTで指定するRPCリクエストを送信してサーバよりレスポンスが返ってきたときに呼ばれるコールバック関数。RPC クライアントからのリクエストに対するサーバからのレスポンス結果を表示している。</p>
<div class="codecolorer-container c mac-classic" style="overflow:auto;white-space:nowrap;border:1px solid #9F9F9F;"><div class="c codecolorer" style="padding:5px;font:normal 12px/1.4em Monaco, Lucida Console, monospace;white-space:nowrap"><span style="color: #993333;">static</span> <span style="color: #993333;">void</span><br />
&nbsp;GetUserCallback<span style="color: #009900;">&#40;</span><span style="color: #993333;">struct</span> evrpc_status <span style="color: #339933;">*</span>status<span style="color: #339933;">,</span><br />
&nbsp; &nbsp; <span style="color: #993333;">struct</span> GetUserRequest <span style="color: #339933;">*</span>req<span style="color: #339933;">,</span> <span style="color: #993333;">struct</span> GetUserResponse <span style="color: #339933;">*</span>res<span style="color: #339933;">,</span> <span style="color: #993333;">void</span> <span style="color: #339933;">*</span>arg<span style="color: #009900;">&#41;</span><br />
<span style="color: #009900;">&#123;</span><br />
&nbsp; &nbsp; <span style="color: #993333;">uint32_t</span> errcode<span style="color: #339933;">;</span><br />
&nbsp; &nbsp; <span style="color: #993333;">char</span> <span style="color: #339933;">*</span>name<span style="color: #339933;">,*</span>email<span style="color: #339933;">;</span><br />
&nbsp; &nbsp; <span style="color: #808080; font-style: italic;">/* check return status */</span><br />
&nbsp; &nbsp; <span style="color: #b1b100;">if</span> <span style="color: #009900;">&#40;</span>status<span style="color: #339933;">-&gt;</span>error <span style="color: #339933;">!=</span> EVRPC_STATUS_ERR_NONE<span style="color: #009900;">&#41;</span> <span style="color: #009900;">&#123;</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; <span style="color: #b1b100;">goto</span> exitloop<span style="color: #339933;">;</span><br />
&nbsp; &nbsp; <span style="color: #009900;">&#125;</span><br />
&nbsp; &nbsp; <span style="color: #808080; font-style: italic;">/* get response info */</span><br />
&nbsp; &nbsp; EVTAG_GET<span style="color: #009900;">&#40;</span>res<span style="color: #339933;">,</span> errcode<span style="color: #339933;">,</span> <span style="color: #339933;">&amp;</span>errcode<span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span><br />
&nbsp; &nbsp; <a href="http://www.opengroup.org/onlinepubs/009695399/functions/fprintf.html"><span style="color: #000066;">fprintf</span></a><span style="color: #009900;">&#40;</span>stdout<span style="color: #339933;">,</span> <span style="color: #ff0000;">&quot;RESPONSE errcode=%d<span style="color: #000099; font-weight: bold;">\n</span>&quot;</span><span style="color: #339933;">,</span> errcode<span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span><br />
&nbsp; &nbsp; <span style="color: #b1b100;">if</span><span style="color: #009900;">&#40;</span>EVTAG_HAS<span style="color: #009900;">&#40;</span>res<span style="color: #339933;">,</span> name<span style="color: #009900;">&#41;</span> <span style="color: #009900;">&#41;</span> <span style="color: #009900;">&#123;</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; EVTAG_GET<span style="color: #009900;">&#40;</span>res<span style="color: #339933;">,</span> name<span style="color: #339933;">,</span> <span style="color: #339933;">&amp;</span>name<span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; <a href="http://www.opengroup.org/onlinepubs/009695399/functions/fprintf.html"><span style="color: #000066;">fprintf</span></a><span style="color: #009900;">&#40;</span>stdout<span style="color: #339933;">,</span> <span style="color: #ff0000;">&quot;RESPONSE name=%s<span style="color: #000099; font-weight: bold;">\n</span>&quot;</span><span style="color: #339933;">,</span> name<span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span><br />
&nbsp; &nbsp; <span style="color: #009900;">&#125;</span><br />
&nbsp; &nbsp; <span style="color: #b1b100;">if</span><span style="color: #009900;">&#40;</span>EVTAG_HAS<span style="color: #009900;">&#40;</span>res<span style="color: #339933;">,</span> email<span style="color: #009900;">&#41;</span> <span style="color: #009900;">&#41;</span> <span style="color: #009900;">&#123;</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; EVTAG_GET<span style="color: #009900;">&#40;</span>res<span style="color: #339933;">,</span> email<span style="color: #339933;">,</span> <span style="color: #339933;">&amp;</span>email<span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; <a href="http://www.opengroup.org/onlinepubs/009695399/functions/fprintf.html"><span style="color: #000066;">fprintf</span></a><span style="color: #009900;">&#40;</span>stdout<span style="color: #339933;">,</span> <span style="color: #ff0000;">&quot;RESPONSE email=%s<span style="color: #000099; font-weight: bold;">\n</span>&quot;</span><span style="color: #339933;">,</span> email<span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span><br />
&nbsp; &nbsp; <span style="color: #009900;">&#125;</span><br />
exitloop<span style="color: #339933;">:</span><br />
&nbsp; &nbsp; event_loopexit<span style="color: #009900;">&#40;</span>NULL<span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span><br />
<span style="color: #009900;">&#125;</span></div></div>
<p>
<h2><strong>ダウンロード、コンパイル、動作確認</strong></h2>
<p>git clone でソースコードを取得してmakeを行う。 リポジトリanyのサブディレクトリ any/libevent_rpcが今回のサンプルにあたる。</p>
<div class="codecolorer-container text mac-classic" style="overflow:auto;white-space:nowrap;border:1px solid #9F9F9F;"><div class="text codecolorer" style="padding:5px;font:normal 12px/1.4em Monaco, Lucida Console, monospace;white-space:nowrap">$ git clone git@github.com:yokawasa/any.git &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;<br />
<br />
Initialized empty Git repository in /home/m/dev/github/any/.git/<br />
remote: Counting objects: 33, done.<br />
remote: Compressing objects: 100% (32/32), done.<br />
remote: Total 33 (delta 7), reused 0 (delta 0)<br />
Receiving objects: 100% (33/33), 11.28 KiB, done.<br />
Resolving deltas: 100% (7/7), done.<br />
<br />
$ cd any/libevent_rpc<br />
$ make<br />
<br />
g++ -I/usr/include -I/usr/local/include -Wall -g -o simple_rpc_client.o -c simple_rpc_client.cpp<br />
gcc -I/usr/include -I/usr/local/include -Wall -g -o simple.gen.o -c simple.gen.c<br />
g++ -L/usr/local/lib -levent -o simple_rpc_client simple_rpc_client.o simple.gen.o<br />
g++ -I/usr/include -I/usr/local/include -Wall -g -o simple_rpc_server.o -c simple_rpc_server.cpp<br />
g++ -L/usr/local/lib -levent -o simple_rpc_server simple_rpc_server.o simple.gen.o</div></div>
<p>これで同ディレクトリにRPCサーバsimple_rpc_server とRPCクライアントsimple_rpc_client実行ファイルのできあがり。simple_rpc_server 、simple_rpc_clientともに実行時に第一引数にサーバアドレス、第二引数にIOポートを指定する。 まずサーバから立ち上げる。</p>
<div class="codecolorer-container text mac-classic" style="overflow:auto;white-space:nowrap;border:1px solid #9F9F9F;"><div class="text codecolorer" style="padding:5px;font:normal 12px/1.4em Monaco, Lucida Console, monospace;white-space:nowrap">$ ./simple_rpc_server localhost 8888</div></div>
<p>サーバが立ち上がったら次のようにクライアントからリクエスト送信する。</p>
<div class="codecolorer-container text mac-classic" style="overflow:auto;white-space:nowrap;border:1px solid #9F9F9F;"><div class="text codecolorer" style="padding:5px;font:normal 12px/1.4em Monaco, Lucida Console, monospace;white-space:nowrap">$ ./simple_rpc_client localhost 8888<br />
RESPONSE errcode=0<br />
RESPONSE name=Fooo Baaar<br />
RESPONSE email=baz@foo.bar</div></div>
<p>上のような結果が出力されればOK。</p>
<p>おわり。</p>
<iframe src="http://www.facebook.com/plugins/like.php?href=http://yk55.com/blog/2010/06/05/libevent_rpc_cs_programmin/&amp;layout=button_count&amp;show_faces=1&amp;width=450&amp;action=like&amp;colorscheme=light&amp;font=arial" scrolling="no" frameborder="0" style="border:none; overflow:hidden; width:450px; height:25px"></iframe>]]></content:encoded>
			<wfw:commentRss>http://yk55.com/blog/2010/06/05/libevent_rpc_cs_programmin/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
	<!-- google_ad_section_end --></channel>
</rss>

