これで我々はサーバの作り方を理解した。 ここでちょっと時間を取ってクライアントを作成してみよう。 これは簡単なので、この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; }
これで終了、簡単だっただろう? これだけ簡単に記述できるのはネットワークに関することをオブジェクトが包み隠してくれているからだ。 その詳細については他のチュートリアルで目にすることもあるかもしれない。
もしこのクライアントを自力でコンパイルしたいなら、ここにソースがある。