2005年07月29日

TCP/IPコネクション型ソケットで非同期通信する方法

TCP/IPのコネクション型ソケット(socket)を使い
プログラム同士を効率よく通信させたいのだけど、
処理をブロッキングすることなく通信させるには
どうしたらよいか悩んだことはありませんか?

今回はプログラム同士が
TCP/IP通信を実現するため、
接続、切断、受信、送信完了の
各事象をイベント駆動型で
プログラムに通知し効率よく通信させる
方法をDelphiでご紹介します。

一般的にTCP/IPのサーバタイプは特定の
サービスをクライアントに提供するため、
特定のポート番号でソケットをオープンし、
クライアントからの接続を待ちます。

一方、TCP/IPのクライアントは特定の
サービスをサーバに要求するため、
サービスを提供している相手(サーバ)と
そのサービスを表すポート番号へ、
ソケットを接続しサービスの要求を行います。

サービスの代表的なものに、
ftp、telnetなどは良くご存知かと思います。
もう少し具体的に見ていくと、
サーバ、クライアントの主な処理は次のようになります。

サーバ処理
説明
@サービスの開始
TCP/IPのストリームソケットを作成(socket)し、自分のIPアドレスとサービスを提供するポート番号をバインド(bind)する。
リッスン(listen)を行い、クライアントから接続を待つ。
サンプルプログラムは、終了するまでこのソケットを維持し、クライアントから接続の要求を受付け続ける。
A接続の受理
@のソケットにクライアントから接続要求があるか検査(select)する。
クライアントから接続要求があった場合、接続を受理(accept)する。
接続の受理に成功した場合、データ送受信用に新しいソケットが確保される。
以降のデータ送受信はこのソケットが使用される。
B要求の受信
Aのソケットでクライアントからデータを受信しているか検査(select)する。
受信データがある場合、取得(recv)する。
Cサービスの実行
クライアントの要求データでサーバのサービスを実行し、必要であれば応答データを戻す。
サンプルプログラムは、クライアントから受信したデータをそのままクライアントへ送信する。
D応答の送信
Cの処理でクライアントへ何らかの応答データを送信する場合、Aのソケットでクライアントへデータを送信できるか検査(select)する。
データを送信できる場合、送信(send)する。
E終了処理
全てのソケットを閉じ(closesocket/close)終了する。

クライアント処理
説明
@接続の要求
TCP/IPのストリームソケットを作成(socket)し、相手(サーバ)のIPアドレスとサーバのポート番号を設定し接続要求(connect)を行う。
サーバがクライアントの接続を受理した場合、接続は成功する。
サーバが不在かサーバのサービスが開始されていない場合、接続は失敗する。
A要求の送信
@のソケットでクライアントが要求データを送信できるか検査(select)する。
データを送信できる場合、送信(send)する。
サンプルプログラムは、画面で入力されたテキストを送信する。
B応答の受信
@のソケットでサーバから応答データを受信しているか検査(select)する。
受信データがある場合、取得(recv)する。
サンプルプログラムは、サーバがクライアントのデータをエコーバックするので、クライアントは自分が送信したテキストを受信する。
C終了処理
全てのソケットを閉じ(closesocket/close)終了する。

ここで問題になるのは
クライアントとサーバ間で
実際にやり取りするデータです。
送受信データの終わりはTCP/IP上に
実装されるプログラムの責任で行う必要があります。


送信データ長がウインドサイズを超えるような
データを送受信する場合、
送信側で仮に一回で送信できたとしても、
受信側では何回かに分けて受信することになります。
select関数はソケットに受信データがあるかないか、
送信できる状態であるかないかの情報は取得できても
送受信データがどこで終わっているか判断がつかないのです。

select関数の受信事象をそれぞれ
バラバラのデータと認識したのでは、
とんでもないことになりますね。
(初心者の方はよくやる失敗ですので注意してくださいね。)

サンプルプログラムは
この問題を回避するため、
送受信データの先頭に
ネットワークバイトオーダーのデータ長を付加し、
送信データが全て送信できた時に送信完了イベントを、
受信データを全て受信できた時に
受信イベントが発生するようになっています。

ではでは、早速サンプルプログラムを見ていただきましょう!

全ソースは【続きを読む】をクリック!

プログラムは若干複雑になってますが、
全ソースを公開しますので、
がんばって理解してくださいね。
また役に立ったと思われるあなた、
いつもの良く冷えた"ビ"がつくものおごってくださいね。(笑い)

【画面イメージ】

SocketTester.gif

関連書籍


Copyright guy@かしらもんじ でぇ〜

続きを読む
posted by guy at 07:20 | 通信編

広告


この広告は60日以上更新がないブログに表示がされております。

以下のいずれかの方法で非表示にすることが可能です。

・記事の投稿、編集をおこなう
・マイブログの【設定】 > 【広告設定】 より、「60日間更新が無い場合」 の 「広告を表示しない」にチェックを入れて保存する。


×

この広告は1年以上新しい記事の投稿がないブログに表示されております。