none
NetworkStream作成後の切断 RRS feed

  • 質問

  • 通信していて、片方が何らかの形で通信を切断してしまった場合、もう片方がNetworkStreamをReadしようとすると例外が発生すると思います。

    そうならないように、Readする前に相手が正常に通信しているか確認するには

    CanReadで確認するということなのでしょうか?

    どうも組んでいて、自信が無いので皆さんに聞いてみました。

    それとも、別の方法があるのでしょうか?

    ネット検索したり、手元にある「Visual C#.netではじめる TCPネットワークプログラミング」(これはとてもわかりやすいです)を読んでもやり方がわからなかったので、ご存知の方教えていただければ幸いです。

    2006年10月23日 16:26

すべての返信

  • 僕もそれほど詳しいわけではありませんが、CanReadプロパティは、NetworkStreamが初期化されたときに設定されるので、そういった用途では利用できないと思います。

    それと、ネットワークではいつデータが届くかはわからないので、タイムアウト値を設定して、例外を捕まえるしかないのではないでしょうか。なお、送信側が正常な手順で接続を閉じた場合は、当たり前ですがReadした場合0が返ります。

    2006年10月24日 10:28
  • 相談にのっていただきありがとうございます。

    僕も教えていただいた方法のようなものを考えたのですが

    途中で絶対にとめることができないものを考えているので、例外を発生させる処理は躊躇してしまいます。

    msdnをみたらcanReadは通信相手がメッセージなり何なりデータを送信してきたときにはtrue,

    そうでない場合はfalseを返すもののようで(多分)、通信を切断したかしてないかといったものではないようですし。

    ネットワークを扱う処理は通信相手の予期せぬ事態に対しての対応がとても難しいと感じています。

    2006年10月25日 1:12
  • ネットワークを扱う処理は通信相手の予期せぬ事態に対しての対応がとても難しいと感じています。

    いやいやいや。予期せぬ事態に対して対応するのが例外処理です。

    例外が発生したら止まるわけではありません。発生した例外に対し適切な処理を行わなかった場合に、最終的にランタイムが実行不能とみなして強制的に終了させるだけです。

    try-catch を使って、発生する例外に対して適切に対処してください。自身では処理できない例外まで捕まえちゃいけませんが。

    canReadは通信相手がメッセージなり何なりデータを送信してきたときにはtrue

    いいえ、違います。そのストリームが読み取り操作をサポートしているかどうかを表すだけです。例えば書き込みモードで開いた FileStream の場合 CanRead は False を返します。

    TCP 接続を元に作った NetworkStream なら CanRead/CanWrite はともに  True を返すでしょう。

    2006年10月25日 3:08
  • >予期せぬ事態に対して対応するのが例外処理です。

    catchで処理を続行しても別に問題ないのですね。

    駄目というかあまり好ましくない方法だと思っていました。ありがとうございます。

    >TCP 接続を元に作った NetworkStream なら CanRead/CanWrite はともに  True を返すでしょう。

    そうですか。TCPのCanReadの認識が間違ってました。

    例外処理でがんばってみます。

    とても勉強になりました。

    2006年10月25日 4:05
  • あれから、いろいろと試してみました。

    書き込み側が不適切(停電・物理的切断など)にネットワークを切断した場合は

    読み取り側がReadすると例外が発生しますが、

    書き込み側がしっかりとCloseした場合は

    読み取り側がReadすると、何事もなかったかのように

    普通にReadして、もちろん書き込みはないですから何も返さない

    処理をし続けます。

    相手がCloseした事を判断するプロパティなりメソッドはないのでしょうか?

     

    2006年10月26日 5:00
  • Close() されていると、すべてのデータを読み込み終わった後で Read() が 0 を返すはずです。
    ぎゃくに Close() されていないと Read() は >0 を返すはずです。
     
    データを読みきらずに recv 側が shutdown されているかどうかを検地するのは、TCP/IP では可能なのかな?
    (無理なきがしますけど)
     
    2006年10月26日 13:58
  • ありがとうございます。

    正常にCloseするとreadは0を返し、文字列が入力された場合は、送信されてきた文字のbyte数を返しますね。

    ただ、やってて疑問なのは空の文字列を送信した場合は、

    readは何も反応しないのです。これはこれでこういうものなんでしょうか。

    それか、そもそも空だと送信側が送る処理をしていないのかとも頭をよぎりました。

    特に問題があるというわけではないのですが、違和感を感じてしまいました。

    それか、空の文字列を送信してreadが0を返すと切断判定ができないから

    わざとそういった仕様にしているのかなとも思いました。以上余談です。

     

    2006年10月30日 2:16