ACE Tutorial 003
Creating a Simple Client


これで我々はサーバの作り方を理解した。 ここでちょっと時間を取ってクライアントを作成してみよう。 これは簡単なので、この1ページだけで済ますとしよう。

Kirthika は「これが1ページクライアントの1段落概要だ。」と言った。


// $Id$


/*
  サーバへソケット接続を確立するために ACE_SOCK_Connector が必要となる。
*/

#include "ace/SOCK_Connector.h"
#include "ace/Log_Msg.h"


/*
  前の二つのチュートリアルと違い、今回はコマンドラインからオプションを受け入れる。
  しかしながら、渡されなかった場合のデフォルト値についても設定しておく。
*/

static u_short SERVER_PORT = ACE_DEFAULT_SERVER_PORT;
static const char *const SERVER_HOST = ACE_DEFAULT_SERVER_HOST;
static const int MAX_ITERATIONS = 4;

int
main (int argc, char *argv[])
{
  
  /*
    ユーザの指定したホストがなければデフォルト値を用いる。
    同様にポート番号と繰り返し回数も指定を受け入れる。
  */

  const char *server_host = argc > 1 ? argv[1] : SERVER_HOST;
  u_short server_port = argc > 2 ? ACE_OS::atoi (argv[2]) : SERVER_PORT;
  int max_iterations = argc > 3 ? ACE_OS::atoi (argv[3]) : MAX_ITERATIONS;

  
  /*
    ストリームソケットを準備する。
    これは信頼できる end-to-end の接続を提供する。
    このオブジェクトを利用して接続先のサーバへデータを送信する。
  */

  ACE_SOCK_Stream server;

  
  /*
    接続を確立するために connector オブジェクトを用意する。
    利用者はサーバのネットワークアドレスを知ってさえいれば、あとは ACE_SOCK_Connector に任せられる。
  */

  ACE_SOCK_Connector connector;

  
  /*
    ここで ACE_INET_Addr オブジェクトを作成する。
    このオブジェクトには接続先サーバのホスト名とポート番号が格納される。
  */

  ACE_INET_Addr addr (server_port,
                      server_host);

  
  /*
    ここで connector の connect() メンバ関数へ Addr とストリームの二つのオブジェクトを渡す。
    これにより目的のサーバへの接続が行われ、ストリームオブジェクトが送受信に利用できるようになる。
  */

  if (connector.connect (server, addr) == -1)
    ACE_ERROR_RETURN ((LM_ERROR,
                       "%p\n",
                       "open"),
                      -1);

  /* ここでサーバへいくつかのメッセージを送る。  */
  for (int i = 0; i < max_iterations; i++)
    {
      char buf[BUFSIZ];

      /* メッセージを番号付きで生成する。 */
      ACE_OS::sprintf (buf,
                       "message = %d\n",
                       i + 1);
      
      /*
        メッセージをサーバへ送信する。
        データを一度に送信するために send_n() 関数を利用する。
        send() という関数もあるのだが、こちらは指定した全データを送信する保証がない。
        これはネットワークバッファ関連の問題による。
        send() がデータ全てを送信できなかった場合には、利用者は素直に諦めるか残りの送信に挑戦できる。
        send_n() 関数は、その残りを送信できるよう挑戦してくれるメソッドなので、今はこちらを使う。

        サーバの send() で見たように send() と send_n() はさらに二つのパラメータを取る。
        タイムアウトパラメータは送信に利用する時間の限度を設定することができる。
        フラグパラメータはOSの send() システムコールへそのまま渡される。
        利用できるフラグについてはマニュアルの send(2) などを参照してほしい。
      */

      if (server.send_n (buf,
                         ACE_OS::strlen (buf)) == -1)
        ACE_ERROR_RETURN ((LM_ERROR,
                           "%p\n",
                           "send"),
                          -1);
      else
        /* 1秒だけ待つ。  */
        ACE_OS::sleep (1);
    }

  
  /*
    サーバへの接続を切断する。
    我々が作成したサーバは ACE_Reactor を基底クラスとしているため、こちらが close() すると適切な handle_input などのアクションを起こす。
    つまり、ソケットに対して読み出しに挑戦し、0バイトの返り値を得ることになる。
    その後、サーバはこちらから接続が閉じられたことを知る。
  */

  if (server.close () == -1)
    ACE_ERROR_RETURN ((LM_ERROR,
                       "%p\n",
                       "close"),
                      -1);
  return 0;
}

これで終了、簡単だっただろう? これだけ簡単に記述できるのはネットワークに関することをオブジェクトが包み隠してくれているからだ。 その詳細については他のチュートリアルで目にすることもあるかもしれない。

もしこのクライアントを自力でコンパイルしたいなら、ここにソースがある。


[インデックスへ]