- PR -

非同期ソケットでの受信タイムアウト設定方法について

投稿者投稿内容
末記人
大ベテラン
会議室デビュー日: 2005/12/05
投稿数: 233
お住まい・勤務地: あわにこ
投稿日時: 2006-04-14 19:57
ちょっと調べてみたらこんなのありましたが参考になりますか?

http://www.microsoft.com/japan/msdn/enterprise/pag/diforwc-ch06.asp
内の【待機アプローチの使用】あたり

コード:
WaitHandle waitHandle = ar.AsyncWaitHandle;
waitHandle.WaitOne(3000, false);



な感じのをデータを受け取って処理する部分に入れれば出来るような気がしますね。

でも、.NETもっていないから実験できません
しろぱんだ
会議室デビュー日: 2006/03/28
投稿数: 11
投稿日時: 2006-04-14 21:28
引用:

Hongliangさんの書き込み (2006-04-14 19:42) より:
様々な要素が影響するものですから一概には言えませんが、数十からのクライアントが同時に接続してきて、かつそれぞれがそれなりに長く接続するというのなら、Socket の非同期接続機構を使った場合、下手するとスレッドプールが枯渇する可能性もあります(CPU 一つにつき 25 スレッドしか並行処理を行いません。これは例えば System.Timers.Timer を処理するスレッドなども含んでの数です)。
自前でスレッドを作成するコストが問題になるのは、HTTP(1.0) のような「大量の接続が要求されるが、一つ一つの接続は短時間」というケースです。例えばブラウザでとあるページを開いても、そのページに含まれる画像など一つ一つに接続が作成されるわけで、一つのクライアントから下手すれば何十とリクエストが生成されます。それが何人ものクライアントから発せられるとなるとそれはもう大変なリクエストの数になりますよね。しかしそれぞれの接続は要求を受けたらファイルを返して切断すれば良いだけですから、一つ一つの接続はごく短い時間で済みます。こういうときは、多すぎる接続は一旦キューに置いて、順次処理していくという構成が成り立ちます。
しかし、一度に処理できる上限を超えた接続は、現在処理している接続が完了するまで待たされるわけで、ある程度一つの接続が長くなるのならこれはいささか問題があります。
とくにスレッドプールを使う場合、こちらで同時処理数を指定できないのがネックになります。
そのくらいの構成なら、自前でスレッドを用意するのも特にそう大きな問題ではないかと思います。


BeginAcceptやBeginReceiveのコールバック関数内の処理が非常に時間のかかる処理であり、同時に数十のクライアントに対応する必要があるのであれば、確かに枯渇(と言うか最大数を超えた分がキューで待機)してしまいますね。
ただ、今回はコールバック関数内の処理にそれほど時間のかからない物なので、その辺りは考慮しなくてもいいのかな、と考えていました。
問題ありな考え方だったかもです。
本当に大量(一万超とか)のスレッドを短期間に生成・破棄を繰り返すことさえなければ、スレッドを(プールを使用せず)生成・破棄してもリソースに多大な影響を与える事はないと考えてよいだろう、という事なんですね。
今回は、素直に接続ごとにスレッドを起動して処理しようかと思います。

しかしながら、非同期メソッドを使いつつタイムアウトを処理する方法が気になってしまいます。
今回考えているようなアプリケーションの場合は、そんな処理は不要だとは分かったのですが、そんな処理が必要になるアプリケーション(どんな物かは思いつかないものの)の場合はどうするのか……。
識者の方々に伺いたいような、伺ってもまだ理解できないような。

引用:

未記入さんの書き込み (2006-04-14 19:57) より:
ちょっと調べてみたらこんなのありましたが参考になりますか?

http://www.microsoft.com/japan/msdn/enterprise/pag/diforwc-ch06.asp
内の【待機アプローチの使用】あたり

コード:
WaitHandle waitHandle = ar.AsyncWaitHandle;
waitHandle.WaitOne(3000, false);



な感じのをデータを受け取って処理する部分に入れれば出来るような気がしますね。

でも、.NETもっていないから実験できません


待機アプローチ、初めて知りました。有難うございます!
進行状況を表示したりする場合はこれを使うものなんですね、勉強になります。
確かに、色々とこねくりまわしたコードを書いたら、何となく処理ができそうな気がします。
今検証できないので何ともあれな回答で申し訳ありません……。
非同期メソッドを使いつつタイムアウトを処理する方法については、まだチャレンジしていきたいので、前に自分が提示した方法と待機アプローチを用いた方法と両方で検証してみようと思います。

上述しましたが、識者の方々、もしよろしければ引き続きご教示下さい。
同期・非同期やマルチスレッド、ソケット通信について、初心者に取っ掛かり易いお薦めの本やサイト等がありましたらこれも教えて頂けると大変有難いです。
unibon
ぬし
会議室デビュー日: 2002/08/22
投稿数: 1532
お住まい・勤務地: 美人谷        良回答(20pt)
投稿日時: 2006-04-16 13:11
普通、こういう場合に、タイムアウトを検出するために待つ手段としては、直接「スレッド」を使うのではなく、「タイマー」を使います。タイマーの内部実装としてスレッドを使うことになるだろうとは思いますが、アプリケーションプログラムからはタイマーだけを使います。悪い出来でないタイマーのクラスならば、スレッドのプーリングなども普通に管理してくれるだろうと思います。

私は .NET のタイマーはあまり良く知らないのですが、
http://www.atmarkit.co.jp/fdotnet/dotnettips/373threadtimer/threadtimer.html
の3つのどれかを使えば良いのではないでしょうか。
System.Threading.Time が良い?

なお、タイマーイベントがファイアされた中で、長時間かかる処理を複数、同時に処理したい時はその中であらためてスレッドを生成することになります。無駄かもしれませんが、切り分けとしてはこのほうがキレイです。
_________________
--
unibon {B73D0144-CD2A-11DA-8E06-0050DA15BC86}

スキルアップ/キャリアアップ(JOB@IT)