<?xml version="1.0" encoding="UTF-8"?>
<rss version="2.0"
     xmlns:content="http://purl.org/rss/1.0/modules/content/"
     xmlns:sy="http://purl.org/rss/1.0/modules/syndication/"
     xmlns:atom="http://www.w3.org/2005/Atom"
     xmlns:dc="http://purl.org/dc/elements/1.1/"
     xmlns:wfw="http://wellformedweb.org/CommentAPI/"
     >
  <channel>
    <title>mojavy.com</title>
    <link>http://mojavy.com/blog</link>
    <description></description>
    <pubDate>Thu, 18 Oct 2012 18:00:01 GMT</pubDate>
    <generator>Blogofile</generator>
    <sy:updatePeriod>hourly</sy:updatePeriod>
    <sy:updateFrequency>1</sy:updateFrequency>
    <item>
      <title>iOSでZeroMQを試す</title>
      <link>http://mojavy.com/blog/2012/10/18/objective-c-zeromq/</link>
      <pubDate>Thu, 18 Oct 2012 18:00:01 JST</pubDate>
      <category><![CDATA[objective-c]]></category>
      <category><![CDATA[ios]]></category>
      <category><![CDATA[zeromq]]></category>
      <category><![CDATA[common lisp]]></category>
      <guid isPermaLink="true">http://mojavy.com/blog/2012/10/18/objective-c-zeromq/</guid>
      <description>iOSでZeroMQを試す</description>
      <content:encoded><![CDATA[<p><img alt="zeromq" src="/images/zeromq-logo.png" /></p>
<p><a href="http://mojavy.com/blog/2012/10/17/common-lisp-zeromq/">前回Common LispでZeroMQを試してみた</a>が、今度はiOSからも試してみた。<a href="http://www.zeromq.org/area:licensing">ZeroMQのライセンス</a>はLGPLだが、static linking exceptionがあるのでiPhoneアプリに組み込んでもソースは公開しなくて大丈夫なはず。(勘違いしてたらごめんなさい)</p>
<h1 id="zeromqiphone">ZeroMQをiPhone用にビルド</h1>
<p>ZeroMQはautotoolsで作成されておりconfigure &amp;&amp; make でビルドできるようになっているが、iPhone用にクロスコンパイルをするためには適切なオプションを与えてやる必要がある。</p>
<p>一応、<a href="http://www.zeromq.org/build:iphone">本家サイト上にもドキュメント</a>はあるが最新のXcodeではうごかない。また、シミュレータ用でもうごかせるようにしておきたい。というわけで、以下のようなビルドスクリプトを書いた。</p>
<script src="https://gist.github.com/3899653.js"> </script>

<p>これをZeroMQのtarを展開してできたディレクトリにbuild.shとかで保存して実行すると、armv7とi386に対応したlibzmq.aができる。</p>
<div class="pygments_borland"><pre><span class="nv">$ </span>tar xzf zeromq-2.2.0.tar.gz
<span class="nv">$ </span><span class="nb">cd </span>zeromq-2.2.0
<span class="nv">$ </span>./build.sh
<span class="nv">$ </span>file libzmq.a
libzmq.a: Mach-O universal binary with 2 architectures
libzmq.a <span class="o">(</span><span class="k">for </span>architecture armv7<span class="o">)</span>:      current ar archive random library
libzmq.a <span class="o">(</span><span class="k">for </span>architecture i386<span class="o">)</span>:       current ar archive random library
</pre></div>

<p>このlibzmq.aと、includeディレクトリの中身をXcodeにインポートしてやればよい。
このときに、XcodeでOther Linker Flags に -lstdc++ を追加してやるのを忘れないように。</p>
<h1 id="zeromq">ZeroMQを用いた簡易チャットアプリ</h1>
<p>サンプルとしてチャットアプリを実装してみる。
チャットでの発言はREQ/REPを用いてアプリ→サーバに渡し、PUB/SUBを用いてサーバ→アプリにブロードキャストする。</p>
<h2 id="_1">サーバ側</h2>
<p>サーバ側はCommon Lispで実装した。単に、rep-sockから発言を受け取ってpub-sockにそのまま流すだけ。</p>
<div class="pygments_borland"><pre>(load &quot;~/.sbclrc&quot;)
(ql:quickload :zeromq)

(defun pull-and-publish ()
  (zmq:with-context (ctx 1)
    (zmq:with-socket (rep-sock ctx zmq:rep)
      (zmq:bind rep-sock &quot;tcp://127.0.0.1:5555&quot;)

      (zmq:with-context (ctx2 1)
        (zmq:with-socket (pub-sock ctx2 zmq:pub)
          (zmq:bind pub-sock &quot;tcp://127.0.0.1:5556&quot;)

          (loop
             (let ((msg (make-instance &#39;zmq:msg)))
               (zmq:recv rep-sock msg)
               (zmq:send rep-sock (make-instance &#39;zmq:msg :data &quot;ok&quot;))
               (zmq:send pub-sock msg))))))))

(pull-and-publish)
</pre></div>

<p>REQ/REPではなくPULL/PUSHでもできるはずだが、なぜかcl-zmqではpullがつかえなかったのでREQ/REPをつかった。</p>
<h2 id="_2">アプリ側</h2>
<p><a href="https://github.com/jeremy-w/objc-zmq">objective-c版ZeroMQ</a>もあるけど、今回はそのままCのAPIを利用した。
以下はソースの抜粋。</p>
<div class="pygments_borland"><pre><span class="cp">#import &quot;ChatViewController.h&quot;</span>
<span class="cp">#import &quot;include/zmq.h&quot;</span>

<span class="k">@interface</span> <span class="nc">ChatViewController</span> <span class="p">()</span> <span class="p">{</span>

    <span class="kt">void</span> <span class="o">*</span><span class="n">ctx1</span><span class="p">,</span> <span class="o">*</span><span class="n">ctx2</span><span class="p">;</span>
    <span class="kt">void</span> <span class="o">*</span><span class="n">subsock</span><span class="p">,</span> <span class="o">*</span><span class="n">reqsock</span><span class="p">;</span>

    <span class="n">NSMutableArray</span> <span class="o">*</span><span class="n">messageList</span><span class="p">;</span>
<span class="p">}</span>
<span class="k">@end</span>

<span class="err">@</span><span class="n">implementation</span> <span class="n">ChatViewController</span>

<span class="k">@synthesize</span> <span class="n">nickname</span><span class="p">;</span>
<span class="k">@synthesize</span> <span class="n">timer</span><span class="p">;</span>

<span class="k">-</span> <span class="p">(</span><span class="kt">void</span><span class="p">)</span><span class="nf">viewDidLoad</span>
<span class="p">{</span>
    <span class="p">[</span><span class="n">super</span> <span class="n">viewDidLoad</span><span class="p">];</span>

    <span class="n">ctx1</span> <span class="o">=</span> <span class="n">zmq_init</span><span class="p">(</span><span class="mi">1</span><span class="p">);</span>
    <span class="n">subsock</span> <span class="o">=</span> <span class="n">zmq_socket</span><span class="p">(</span><span class="n">ctx1</span><span class="p">,</span> <span class="n">ZMQ_SUB</span><span class="p">);</span>
    <span class="n">zmq_setsockopt</span><span class="p">(</span><span class="n">subsock</span><span class="p">,</span> <span class="n">ZMQ_SUBSCRIBE</span><span class="p">,</span> <span class="s">&quot;&quot;</span><span class="p">,</span> <span class="mi">0</span><span class="p">);</span>
    <span class="kt">int</span> <span class="n">rc</span> <span class="o">=</span> <span class="n">zmq_connect</span><span class="p">(</span><span class="n">subsock</span><span class="p">,</span> <span class="s">&quot;tcp://127.0.0.1:5556&quot;</span><span class="p">);</span>
    <span class="n">assert</span><span class="p">(</span><span class="n">rc</span> <span class="o">==</span> <span class="mi">0</span><span class="p">);</span>

    <span class="n">ctx2</span> <span class="o">=</span> <span class="n">zmq_init</span><span class="p">(</span><span class="mi">1</span><span class="p">);</span>
    <span class="n">reqsock</span> <span class="o">=</span> <span class="n">zmq_socket</span><span class="p">(</span><span class="n">ctx1</span><span class="p">,</span> <span class="n">ZMQ_REQ</span><span class="p">);</span>
    <span class="n">rc</span> <span class="o">=</span> <span class="n">zmq_connect</span><span class="p">(</span><span class="n">reqsock</span><span class="p">,</span> <span class="s">&quot;tcp://127.0.0.1:5555&quot;</span><span class="p">);</span>
    <span class="n">assert</span><span class="p">(</span><span class="n">rc</span> <span class="o">==</span> <span class="mi">0</span><span class="p">);</span>

    <span class="n">self</span><span class="p">.</span><span class="n">timer</span> <span class="o">=</span> <span class="p">[</span><span class="n">NSTimer</span> <span class="nl">scheduledTimerWithTimeInterval:</span><span class="mi">1</span> <span class="nl">target:</span><span class="n">self</span> <span class="nl">selector:</span><span class="k">@selector</span><span class="p">(</span><span class="n">observeSocket</span><span class="p">)</span> <span class="nl">userInfo:</span><span class="nb">nil</span> <span class="nl">repeats:</span><span class="n">YES</span><span class="p">];</span>
    <span class="n">messageList</span> <span class="o">=</span> <span class="p">[[</span><span class="n">NSMutableArray</span> <span class="n">alloc</span><span class="p">]</span> <span class="n">init</span><span class="p">];</span>
<span class="p">}</span>

<span class="k">-</span> <span class="p">(</span><span class="kt">void</span><span class="p">)</span><span class="nf">viewWillDisappear:</span><span class="p">(</span><span class="kt">BOOL</span><span class="p">)</span><span class="nv">animated</span>
<span class="p">{</span>
    <span class="p">[</span><span class="n">self</span><span class="p">.</span><span class="n">timer</span> <span class="n">invalidate</span><span class="p">];</span>
    <span class="n">zmq_close</span><span class="p">(</span><span class="n">subsock</span><span class="p">);</span>
    <span class="n">zmq_close</span><span class="p">(</span><span class="n">reqsock</span><span class="p">);</span>
    <span class="n">zmq_term</span><span class="p">(</span><span class="n">ctx1</span><span class="p">);</span>
    <span class="n">zmq_term</span><span class="p">(</span><span class="n">ctx2</span><span class="p">);</span>
<span class="p">}</span>

<span class="k">-</span> <span class="p">(</span><span class="kt">void</span><span class="p">)</span><span class="nf">observeSocket</span>
<span class="p">{</span>
    <span class="n">zmq_msg_t</span> <span class="n">msg</span><span class="p">;</span>
    <span class="kt">int</span> <span class="n">rc</span> <span class="o">=</span> <span class="n">zmq_msg_init</span><span class="p">(</span><span class="o">&amp;</span><span class="n">msg</span><span class="p">);</span>
    <span class="n">assert</span><span class="p">(</span><span class="n">rc</span> <span class="o">==</span> <span class="mi">0</span><span class="p">);</span>

    <span class="k">do</span> <span class="p">{</span>
        <span class="n">rc</span> <span class="o">=</span> <span class="n">zmq_recv</span><span class="p">(</span><span class="n">subsock</span><span class="p">,</span> <span class="o">&amp;</span><span class="n">msg</span><span class="p">,</span> <span class="n">ZMQ_NOBLOCK</span><span class="p">);</span>
        <span class="k">if</span> <span class="p">(</span><span class="n">rc</span> <span class="o">==</span> <span class="n">EAGAIN</span><span class="p">)</span> <span class="p">{</span>
            <span class="n">NSLog</span><span class="p">(</span><span class="s">@&quot;no data available&quot;</span><span class="p">);</span>
        <span class="p">}</span> <span class="k">else</span> <span class="k">if</span> <span class="p">(</span><span class="n">rc</span> <span class="o">==</span> <span class="n">ENOTSUP</span><span class="p">)</span> <span class="p">{</span>
            <span class="n">NSLog</span><span class="p">(</span><span class="s">@&quot;ENOTSUP&quot;</span><span class="p">);</span>
        <span class="p">}</span> <span class="k">else</span> <span class="k">if</span> <span class="p">(</span><span class="n">rc</span> <span class="o">==</span> <span class="n">EFSM</span><span class="p">)</span> <span class="p">{</span>
            <span class="n">NSLog</span><span class="p">(</span><span class="s">@&quot;EFSM&quot;</span><span class="p">);</span>
        <span class="p">}</span> <span class="k">else</span> <span class="k">if</span> <span class="p">(</span><span class="n">rc</span> <span class="o">==</span> <span class="n">ETERM</span><span class="p">)</span> <span class="p">{</span>
            <span class="n">NSLog</span><span class="p">(</span><span class="s">@&quot;ETERM&quot;</span><span class="p">);</span>
        <span class="p">}</span> <span class="k">else</span> <span class="k">if</span> <span class="p">(</span><span class="n">rc</span> <span class="o">==</span> <span class="n">ENOTSOCK</span><span class="p">)</span> <span class="p">{</span>
            <span class="n">NSLog</span><span class="p">(</span><span class="s">@&quot;ENOTSOCK&quot;</span><span class="p">);</span>
        <span class="p">}</span> <span class="k">else</span> <span class="k">if</span> <span class="p">(</span><span class="n">rc</span> <span class="o">==</span> <span class="n">EINTR</span><span class="p">)</span> <span class="p">{</span>
            <span class="n">NSLog</span><span class="p">(</span><span class="s">@&quot;EINTR&quot;</span><span class="p">);</span>
        <span class="p">}</span> <span class="k">else</span> <span class="k">if</span> <span class="p">(</span><span class="n">rc</span> <span class="o">==</span> <span class="n">EFAULT</span><span class="p">)</span> <span class="p">{</span>
            <span class="n">NSLog</span><span class="p">(</span><span class="s">@&quot;EFAULT&quot;</span><span class="p">);</span>
        <span class="p">}</span> <span class="k">else</span> <span class="k">if</span> <span class="p">(</span><span class="n">rc</span> <span class="o">==</span> <span class="mi">0</span><span class="p">)</span> <span class="p">{</span>
            <span class="n">size_t</span> <span class="n">siz</span> <span class="o">=</span> <span class="n">zmq_msg_size</span><span class="p">(</span><span class="o">&amp;</span><span class="n">msg</span><span class="p">);</span>
            <span class="kt">void</span> <span class="o">*</span><span class="n">dat</span> <span class="o">=</span> <span class="n">zmq_msg_data</span><span class="p">(</span><span class="o">&amp;</span><span class="n">msg</span><span class="p">);</span>
            <span class="n">NSString</span> <span class="o">*</span><span class="n">str</span> <span class="o">=</span> <span class="p">[[</span><span class="n">NSString</span> <span class="n">alloc</span><span class="p">]</span> <span class="nl">initWithData:</span><span class="p">[</span><span class="n">NSData</span> <span class="nl">dataWithBytes:</span><span class="n">dat</span> <span class="nl">length:</span><span class="n">siz</span><span class="p">]</span> <span class="nl">encoding:</span><span class="n">NSUTF8StringEncoding</span><span class="p">];</span>
            <span class="p">[</span><span class="n">messageList</span> <span class="nl">insertObject:</span><span class="n">str</span> <span class="nl">atIndex:</span><span class="mi">0</span><span class="p">];</span>
        <span class="p">}</span> <span class="k">else</span> <span class="p">{</span>
            <span class="n">NSLog</span><span class="p">(</span><span class="s">@&quot;unknown&quot;</span><span class="p">);</span>
        <span class="p">}</span>
    <span class="p">}</span> <span class="k">while</span> <span class="p">(</span><span class="n">rc</span> <span class="o">==</span> <span class="mi">0</span><span class="p">);</span>
    <span class="n">zmq_msg_close</span><span class="p">(</span><span class="o">&amp;</span><span class="n">msg</span><span class="p">);</span>
    <span class="p">[</span><span class="n">self</span><span class="p">.</span><span class="n">tableView</span> <span class="n">reloadData</span><span class="p">];</span>
<span class="p">}</span>

<span class="k">-</span> <span class="p">(</span><span class="kt">IBAction</span><span class="p">)</span> <span class="nf">saySomething:</span><span class="p">(</span><span class="kt">id</span><span class="p">)</span><span class="nv">sender</span>
<span class="p">{</span>
    <span class="n">UIAlertView</span> <span class="o">*</span><span class="n">alert</span> <span class="o">=</span> <span class="p">[[</span><span class="n">UIAlertView</span> <span class="n">alloc</span><span class="p">]</span> <span class="nl">initWithTitle:</span><span class="s">@&quot;text input&quot;</span>
                                <span class="nl">message:</span><span class="s">@&quot;&quot;</span>
                               <span class="nl">delegate:</span><span class="n">self</span>
                      <span class="nl">cancelButtonTitle:</span><span class="s">@&quot;cancel&quot;</span>
                      <span class="nl">otherButtonTitles:</span><span class="s">@&quot;ok&quot;</span><span class="p">,</span> <span class="nb">nil</span><span class="p">];</span>
    <span class="n">alert</span><span class="p">.</span><span class="n">alertViewStyle</span> <span class="o">=</span> <span class="n">UIAlertViewStylePlainTextInput</span><span class="p">;</span>
    <span class="p">[</span><span class="n">alert</span> <span class="n">show</span><span class="p">];</span>
<span class="p">}</span>

<span class="k">-</span> <span class="p">(</span><span class="kt">void</span><span class="p">)</span><span class="nf">alertView:</span><span class="p">(</span><span class="n">UIAlertView</span><span class="o">*</span><span class="p">)</span><span class="nv">alertView</span> <span class="nf">clickedButtonAtIndex:</span><span class="p">(</span><span class="n">NSInteger</span><span class="p">)</span><span class="nv">buttonIndex</span>
<span class="p">{</span>
    <span class="n">zmq_msg_t</span> <span class="n">msg</span><span class="p">;</span>
    <span class="kt">int</span> <span class="n">rc</span><span class="p">;</span>
    <span class="n">NSData</span> <span class="o">*</span><span class="n">data</span><span class="p">;</span>
    <span class="n">NSString</span> <span class="o">*</span><span class="n">str</span><span class="p">;</span>

    <span class="k">switch</span> <span class="p">(</span><span class="n">buttonIndex</span><span class="p">)</span> <span class="p">{</span>
        <span class="k">case</span> <span class="mi">0</span><span class="o">:</span>
            <span class="k">break</span><span class="p">;</span>
        <span class="k">case</span> <span class="mi">1</span><span class="o">:</span>
            <span class="n">str</span> <span class="o">=</span> <span class="p">[</span><span class="n">NSString</span> <span class="nl">stringWithFormat:</span><span class="s">@&quot;%@: %@&quot;</span><span class="p">,</span> <span class="n">nickname</span><span class="p">,</span> <span class="p">[</span><span class="n">alertView</span> <span class="nl">textFieldAtIndex:</span><span class="mi">0</span><span class="p">].</span><span class="n">text</span><span class="p">];</span>
            <span class="n">data</span> <span class="o">=</span> <span class="p">[</span><span class="n">str</span> <span class="nl">dataUsingEncoding:</span><span class="n">NSUTF8StringEncoding</span><span class="p">];</span>
            <span class="n">rc</span> <span class="o">=</span> <span class="n">zmq_msg_init_size</span><span class="p">(</span><span class="o">&amp;</span><span class="n">msg</span><span class="p">,</span> <span class="p">[</span><span class="n">data</span> <span class="n">length</span><span class="p">]);</span>
            <span class="n">assert</span><span class="p">(</span><span class="n">rc</span> <span class="o">==</span> <span class="mi">0</span><span class="p">);</span>
            <span class="n">memcpy</span><span class="p">(</span><span class="n">zmq_msg_data</span><span class="p">(</span><span class="o">&amp;</span><span class="n">msg</span><span class="p">),</span> <span class="p">[</span><span class="n">data</span> <span class="n">bytes</span><span class="p">],</span> <span class="p">[</span><span class="n">data</span> <span class="n">length</span><span class="p">]);</span>

            <span class="n">zmq_send</span><span class="p">(</span><span class="n">reqsock</span><span class="p">,</span> <span class="o">&amp;</span><span class="n">msg</span><span class="p">,</span> <span class="mi">0</span><span class="p">);</span>
            <span class="n">zmq_recv</span><span class="p">(</span><span class="n">reqsock</span><span class="p">,</span> <span class="o">&amp;</span><span class="n">msg</span><span class="p">,</span> <span class="mi">0</span><span class="p">);</span>
            <span class="n">zmq_msg_close</span><span class="p">(</span><span class="o">&amp;</span><span class="n">msg</span><span class="p">);</span>
            <span class="k">break</span><span class="p">;</span>
        <span class="k">default</span><span class="o">:</span>
            <span class="k">break</span><span class="p">;</span>
    <span class="p">}</span>
<span class="p">}</span>

<span class="k">@end</span>
</pre></div>

<p>以下補足</p>
<ul>
<li>簡単のためタイマーで1秒ごとにソケットにメッセージがあるかどうかobserveSocketでチェックしているが、別スレッドにしたほうがスマート</li>
<li><a href="http://api.zeromq.org/2-2:zmq-recv">zmq_recvのマニュアル</a>によると、zmq_recvをZMQ_NOBLOCKで呼んだときにメッセージがなかった場合はEAGAINが返るとなっているが、-1がかえってきていた。</li>
<li>上記ソースはUITableViewControllerで発言を表示する想定になっているが、UIまわりのコードは省略</li>
</ul>
<h2 id="common-lisp">オマケ(Common Lisp版コマンドライン用チャットクライアント)</h2>
<div class="pygments_borland"><pre>(load &quot;~/.sbclrc&quot;)
(ql:quickload :zeromq)
(ql:quickload :bordeaux-threads)

(defun sub ()
  (zmq:with-context (ctx 1)
    (zmq:with-socket (socket ctx zmq:sub)
      (zmq:setsockopt socket zmq:subscribe &quot;&quot;)
      (zmq:connect socket &quot;tcp://127.0.0.1:5556&quot;)
      (loop
         (let ((query (make-instance &#39;zmq:msg)))
           (zmq:recv socket query)
           (format t &quot;received message: ~a~%&quot; (zmq:msg-data-as-string query)))))))

(defun client ()
  (zmq:with-context (ctx 1)
    (zmq:with-socket (socket ctx zmq:req)
      (zmq:connect socket &quot;tcp://127.0.0.1:5555&quot;)
      (loop
         (zmq:send socket (make-instance &#39;zmq:msg
                                         :data (read-line)))
         (let ((result (make-instance &#39;zmq:msg)))
           (zmq:recv socket result))))))

(bordeaux-threads:make-thread #&#39;sub)
(client)
</pre></div>

<h1 id="_3">まとめ</h1>
<ul>
<li>iPhoneでZeroMQを動かしてみた</li>
<li>ZeroMQのREQ/REPとPUB/SUBを使用してチャットをつくってみた</li>
<li>appleの審査を通過するかどうかは知らない(一応実績はあるらしい)</li>
</ul>
<h1 id="_4">参考</h1>
<ul>
<li><a href="http://api.zeromq.org/2-2:_start">http://api.zeromq.org/2-2:_start</a></li>
<li><a href="http://www.zeromq.org/area:licensing">http://www.zeromq.org/area:licensing</a></li>
<li><a href="http://www.zeromq.org/intro:commercial-support">http://www.zeromq.org/intro:commercial-support</a></li>
</ul>]]></content:encoded>
    </item>
    <item>
      <title>Common LispでZeroMQを試す</title>
      <link>http://mojavy.com/blog/2012/10/17/common-lisp-zeromq/</link>
      <pubDate>Wed, 17 Oct 2012 00:00:00 JST</pubDate>
      <category><![CDATA[zeromq]]></category>
      <category><![CDATA[sbcl]]></category>
      <category><![CDATA[common lisp]]></category>
      <guid isPermaLink="true">http://mojavy.com/blog/2012/10/17/common-lisp-zeromq/</guid>
      <description>Common LispでZeroMQを試す</description>
      <content:encoded><![CDATA[<p><img alt="zeromq" src="/images/zeromq-logo.png" /></p>
<p>Common LispでZeroMQを試してみた。</p>
<p>使用環境は以下のとおり</p>
<ul>
<li>OS: Ubuntu 12.04 LTS</li>
<li>Common Lisp 処理系：<a href="http://www.sbcl.org/">sbcl (1.0.55.0.debian)</a></li>
<li><a href="http://download.zeromq.org/zeromq-2.2.0.tar.gz">ZeroMQ 2.2.0</a></li>
</ul>
<h1 id="1-quicklisp">1. quicklispのインストール</h1>
<p>以下を参考にquicklispをインストールする。</p>
<ul>
<li><a href="http://www.quicklisp.org/beta/">Quicklisp</a></li>
<li><a href="http://modern-cl.blogspot.jp/2011/03/quicklisp.html">第2回 Quicklispによるライブラリ環境</a></li>
</ul>
<div class="pygments_borland"><pre><span class="nv">$ </span>curl -O http://beta.quicklisp.org/quicklisp.lisp
<span class="nv">$ </span>sbcl
<span class="o">(</span>load <span class="s2">&quot;quicklisp.lisp&quot;</span><span class="o">)</span>
<span class="o">(</span>quicklisp-quickstart:install :path <span class="s2">&quot;.quicklisp/&quot;</span><span class="o">)</span>
<span class="o">(</span>ql:add-to-init-file<span class="o">)</span>
</pre></div>

<p>※ (quicklisp-quickstart:install :path ".quicklisp/") のパスで最後のスラッシュは省略不可</p>
<h1 id="2-cl-zmq">2. cl-zmqのインストール</h1>
<div class="pygments_borland"><pre>(ql:quickload :zeromq)
</pre></div>

<p>ここで以下のようなエラーがでる場合はzeromqのインストールができていないか、ld.so.confに問題がある。ld.so.confにzeromqをインストールしたディレクトリがはいってることを確認して、sudo ldconfig すればちゃんとロードされるはず。</p>
<div class="pygments_borland"><pre>debugger invoked on a LOAD-FOREIGN-LIBRARY-ERROR in thread
<span class="c">#&lt;THREAD &quot;initial thread&quot; RUNNING {10029990A3}&gt;:</span>
  Unable to load any of the alternatives:
   <span class="o">(</span><span class="s2">&quot;libzmq.so.0.0.0&quot;</span> <span class="s2">&quot;libzmq.so&quot;</span><span class="o">)</span>

Type HELP <span class="k">for </span>debugger <span class="nb">help</span>, or <span class="o">(</span>SB-EXT:QUIT<span class="o">)</span> to <span class="nb">exit </span>from SBCL.

restarts <span class="o">(</span>invokable by number or by possibly-abbreviated name<span class="o">)</span>:
  0: <span class="o">[</span>RETRY          <span class="o">]</span> Try loading the foreign library again.
  1: <span class="o">[</span>USE-VALUE      <span class="o">]</span> Use another library instead.
  2: <span class="o">[</span>TRY-RECOMPILING<span class="o">]</span> Recompile package and try loading it again
  3: <span class="o">[</span>RETRY          <span class="o">]</span> Retry
                       loading FASL <span class="k">for</span> <span class="c">#&lt;CL-SOURCE-FILE &quot;zeromq&quot; &quot;package&quot;&gt;.</span>
  4: <span class="o">[</span>ACCEPT         <span class="o">]</span> Continue, treating
                       loading FASL <span class="k">for</span> <span class="c">#&lt;CL-SOURCE-FILE &quot;zeromq&quot; &quot;package&quot;&gt; as</span>
                       having been successful.
  5: <span class="o">[</span>ABORT          <span class="o">]</span> Give up on <span class="s2">&quot;zeromq&quot;</span>
  6:                   Exit debugger, returning to top level.

<span class="o">(</span>CFFI::FL-ERROR
 <span class="s2">&quot;Unable to load any of the alternatives:~%   ~S&quot;</span>
 <span class="o">(</span><span class="s2">&quot;libzmq.so.0.0.0&quot;</span> <span class="s2">&quot;libzmq.so&quot;</span><span class="o">))</span>
0<span class="o">]</span> 2
</pre></div>

<p>以下のようにしてライブラリのパスを設定してやっても回避はできるがおすすめしない。</p>
<div class="pygments_borland"><pre>(pushnew &quot;/path/to/lib/&quot; *foreign-library-directories*)
</pre></div>

<p><a href="http://common-lisp.net/project/cffi/manual/html_node/_002aforeign_002dlibrary_002ddirectories_002a.html">http://common-lisp.net/project/cffi/manual/html_node/_002aforeign_002dlibrary_002ddirectories_002a.html</a></p>
<h1 id="3">3. サーバ側起動</h1>
<p><a href="http://www.cliki.net/cl-zmq">cl-zmq</a> のサンプルコード参考に以下のようなエコーサーバを書いた。これをserver.lispに保存して、 sbcl --script server.lisp で実行。ちなみに、127.0.0.1:5555 の部分をlocalhost:5555のように書くとNo such deviceといわれる。 (参考 <a href="http://stackoverflow.com/questions/6024003/why-doesnt-zeromq-work-on-localhost">Why doesn't zeromq work on localhost?</a> )</p>
<div class="pygments_borland"><pre>(load &quot;~/.sbclrc&quot;)
(ql:quickload :zeromq)

(defun server ()
  (zmq:with-context (ctx 1)
    (zmq:with-socket (socket ctx zmq:rep)
      (zmq:bind socket &quot;tcp://127.0.0.1:5555&quot;)
      (loop
         (let ((query (make-instance &#39;zmq:msg)))
           (zmq:recv socket query)
           (let ((req-string (zmq:msg-data-as-string query)))
             (format t &quot;Recieved message: &#39;~A&#39;~%&quot; req-string)
             (zmq:send socket (make-instance &#39;zmq:msg :data req-string)) ))))))

(server)
</pre></div>

<h1 id="4">4. クライアント側起動</h1>
<p>こちらも同様に以下をclient.lispに保存して、sbcl --script client.lispで実行。うまくいけばサーバ側からレスポンスが返ってくる。</p>
<div class="pygments_borland"><pre>(load &quot;~/.sbclrc&quot;)
(ql:quickload :zeromq)

(defun client ()
  (zmq:with-context (ctx 1)
    (zmq:with-socket (socket ctx zmq:req)
      (zmq:connect socket &quot;tcp://127.0.0.1:5555&quot;)
      (loop
      (zmq:send socket (make-instance &#39;zmq:msg
                                      :data (read-line)))
      (let ((result (make-instance &#39;zmq:msg)))
        (zmq:recv socket result)
        (format t &quot;Recieved message: &#39;~A&#39;~%&quot;
                (zmq:msg-data-as-string result) ))))))

(client)
</pre></div>

<h1 id="_1">まとめ</h1>
<p>Common Lisp(sbcl)でZeroMQを利用して、簡単なエコーサーバ/クライアントを実装した。</p>
<h1 id="_2">参考</h1>
<ul>
<li><a href="http://www.cliki.net/cl-zmq">cl-zmq</a></li>
<li><a href="http://stackoverflow.com/questions/6024003/why-doesnt-zeromq-work-on-localhost">Why doesn't zeromq work on localhost?</a></li>
</ul>]]></content:encoded>
    </item>
  </channel>
</rss>
