したらばTOP ■掲示板に戻る■ 全部 1-100 最新50 | メール | |

VB2005のSocket通信の複数クライアントの非同期処理

1まもる:2011/06/02(木) 09:56:43
VB2005のSocket通信の複数クライアントの非同期処理について
このサイトで勉強さてて頂いております。

ソケットの切断検知について、壁に当たってしまい
ご教示して頂けたらと思い、書込み致しました。

サーバ側のLANコネクタ切断時は検知できますが
クライアント側のLANコネクタ切断の検知できず、困っております。

netstatを使ってポートの状態を確認してみますと
ポートが占有されたままになってるように思います。

接続してから一定時間経過したら
切断させるように出来れば…等
色々考えてみましたが
私の能力不足で解決策が見当たりませんでした。

なにか切断を検知する方法がありますでしょうか?

お忙しいとは思いますが、宜しくお願いします。

2igoten:2011/06/02(木) 11:09:56
非同期の場合物理的なSocketの切断を判別するのは
難しいですね。
pingはネットワークの物理的な接続テストにも使われますので
pingを飛ばす方法が良いと思います。

3まもる:2011/06/02(木) 16:14:19
お忙しい中、回答ありがとうございます。

色々調べていたのですが
私の知識不足でpingという考えが出てきませんでした。

ご教示通りに、Pingを組み込んでみたところ
ステータスでTimeOutを検知できるようになりました。

タイムアウト検知できるようになりましたので
残った通信をしているスレッドを破棄しようと考えているのですが
(通信を行っているスレッド=コードの構成にあります図の「クライアントクラス毎の別スレッド上のRead」だと考えています)
ここでまた壁に当たってしまいました。

メインフォームからタイムアウトを検知したスレッドを破棄する方法が分かりません…。
ご教示頂いてから、色々手立てを考え、調べてみたのですが悪戦苦闘しております。

連続で大変恐縮なのですが
通信を行っているスレッドの破棄する方法をご教示して頂けませんでしょうか?

4igoten:2011/06/02(木) 18:56:40
ServerListen()の中の catch (Exception ex)の
切断処理と同じ処理を行えばいいと思います。

5まもる:2011/06/03(金) 09:40:48
ご返答、ありがとうございます。

ご教示通り、切断処理を行おうと思ったのですが
ServerListen() の Catch ex As Exception はデリゲートでメインフォームに対してエラーを書き込んでるように見受けられます。
ServerStart() の Catch ex As Exception の方かな?と思いましたので、調べてみましたが
Listener.[Stop]()を行いますと、コードの構成にあります図の、"別スレッド上のListen"が停止されてしまい
その子供の接続中の全ての通信が終了してしまいますので、こちらでも無いようです。
"別スレッド上のListen"は破棄しないで
通信を行っていると思います子供の"クライアントクラス毎の別スレッド上のRead"のみを停止できないでしょうか?

質問が連続しまして、真に申し訳ありませんが
宜しくお願いします。

6igoten:2011/06/03(金) 10:48:02
サーバーの別スレッドは一つで、その中で複数の接続要求を
受け付けます。
クライアントからの接続要求が来ると、サーバーは新しいソケット
を作成しクライアントの接続を許可します。
そしてClientHandlerクラスのインスタンスを作成して、その接続を
保持します。
更にlist<T>にそのインスタンスを保持させます。
サーバーがクライアントの文字を受信したときは、
OnReadComplete(IAsyncResult ar)に割り込みが発生しますので
この中で受信処理をしますが、いったいどのクライアントから送らせて
来たかの情報は引数のarで渡ってきます。
fomServer.Invoke (new dlgWriteText(fomServer.WriteReadText)
, new object[] { this,strGetText });
はメインスレッドに対して受信文字の書き込みを指示しますが、
このthisは文字を受信したClientHandlerのインスタンスです。
メインスレッドのWriteReadText(ClientHandler cl, string text)は
引数に受信したソケットのインスタンスを受け取りますので、
このインスタンスとList<T>に保存されているインスタンスを比較して
どのクライアントからの送信か判断して受信文字を書き込みます。

さて、LANのソケットが抜けた場合は機器の故障と同じで、
ソケットの情報がどうなるかは未定です。
通常クライアントが切断されると、
OnReadComplete(IAsyncResult ar)にコールバックがかかり
読み込み文字が無いのでelse以下で、
        //終了ボタンが押され場合はここに落ちる
//クライアントのListからの削除
fomServer.Invoke(new dlgsetList(fomServer.deleteClient)
, new object[] { this });

networkStream.Close();
socket.Close();
networkStream = null;
Thread.Sleep(20);//これを入れないとNullReferenceExceptionが起きる
socket = null;
の処理を行いますがLANケーブルが抜けた場合は相手の応答が無いので、
fomServer.Invoke(new dlgsetList(fomServer.deleteClient)
, new object[] { this });
位しか出来ないかもしれません。

7まもる:2011/06/03(金) 21:13:36
>そしてClientHandlerクラスのインスタンスを作成して、その接続を
>保持します。
ClientHandlerはServerListenを行うスレッドと同じように
別スレッドで動いているのかと、勘違いしておりました・・・。
丁寧に解説していただき、ありがとうございます。

igoten様にこれまでご教示して頂きました事を念頭にしまして
ClientHandlerクラスにクローズだけを行う処理を追加しまして
メインフォームで定周期でピングを行いつつ
Timeoutを検知したタイミングで
ClientHandlerクラスに追加しましたクローズ処理を行うようにしてみました。
クローズ処理後は保持したインスタンスを削除するようにしております。

実際に切断検知後、ポートも正常に閉じるようになりました。

未だに悪戦苦闘しておりますが
クライアント側の切断も検知出切る事がわかりました。
ありがとうございます!
ここ数日間、初心者の私にとりまして、大変勉強になりました。

まだまだ理解度が足りていませんので
引き続きこのサイトで勉強させて頂きます。

貴重なお時間を割いていただき
本当にありがとうございました。

11<削除>:<削除>
<削除>


新着レスの表示


名前: E-mail(省略可)

※書き込む際の注意事項はこちら

※画像アップローダーはこちら

(画像を表示できるのは「画像リンクのサムネイル表示」がオンの掲示板に限ります)

掲示板管理者へ連絡 無料レンタル掲示板