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