C# と VB.NET の質問掲示板

ASP.NET、C++/CLI、Java 何でもどうぞ

C# と VB.NET の入門サイト

Re[7]: C# 、TCP通信処理時の受信待ち処理について


(過去ログ 64 を表示中)

[トピック内 10 記事 (1 - 10 表示)]  << 0 >>

■36921 / inTopicNo.1)  C# 、TCP通信処理時の受信待ち処理について
  
□投稿者/ non (1回)-(2009/06/10(Wed) 02:26:19)

分類:[C#] 

C#でTCPを使用した通信クライアントを作成しています。

通信(TcpClient)、ストリームアクセス(NetworkStream, StreamReader and StreamWriter)の各クラスはとてもシンプルで特に問題ないのですが、
データ受信待ちの処理で少し迷っています。

TCP通信の処理は初めてなのですが、受信処理はブロックされますよね?
とりあえず受信専用のThreadでループ監視をして文字列の汎用リストに結果の文字列を格納し、定期的にそのリストから文字列郡を取り出して解析する・・といった処理を入れてみたのですが、たまにそのリスト内にNull文字列が混じっているようなのです。

TCP受信では文字列(空文字列""を含めて)でなくてもReaderが反応する事があるのでしょうか?


引用返信 編集キー/
■36923 / inTopicNo.2)  Re[1]: C# 、TCP通信処理時の受信待ち処理について
□投稿者/ れい (845回)-(2009/06/10(Wed) 07:00:56)
No36921 (non さん) に返信
> 通信(TcpClient)、ストリームアクセス(NetworkStream, StreamReader and StreamWriter)の各クラスはとてもシンプルで特に問題ないのですが、
> データ受信待ちの処理で少し迷っています。
>
> TCP通信の処理は初めてなのですが、受信処理はブロックされますよね?

上記のクラスを使っているならStreamReader.Read/ReadBlock/ReadLine/ReadToEndなどでブロックすると思います。
実際には、各メソッド内のNetworkStream.Readがブロックしていて、
NetworkStream.ReadはTCPの受信待ちをしている、となります。

> とりあえず受信専用のThreadでループ監視をして文字列の汎用リストに結果の文字列を格納し、定期的にそのリストから文字列郡を取り出して解析する・・といった処理を入れてみたのですが、たまにそのリスト内にNull文字列が混じっているようなのです。
>
> TCP受信では文字列(空文字列""を含めて)でなくてもReaderが反応する事があるのでしょうか?

「文字列でなくても」「Readerが反応」の意味がよくわかりませんが、
StreamReader.Readのブロック状態が終わるという解釈で話を進めます。

.NetのStreamのデザインは、「Readの返値は実際に読んだバイト数で、Readで0が返ったらStreamの末尾」です。
これはバークレーソケットでも同じです。
さらに、TextReader(StreamReader)のReadメソッド類も似たデザインになっています。

なので、
> TCP受信では文字列(空文字列""を含めて)でなくてもReaderが反応する事があるのでしょうか?
終了したTCP接続にReadを行うといつでも0が返り、一文字も読めません。
Readで待機している際にStreamが閉じた場合も同様に0が返り、一文字も読めないのにブロックが解除されます。

これが「Readerが反応する」ケースの一つです。
この場合、StreamReader.EndOfStream=trueとなります。

もう一つが、Stream.ReadやTextReader.Readのcount引数に0を入れた場合です。
この場合、ブロックせずに直ちに戻り、0を返します。

それ以外でブロックが解除され、正しく戻るケースは…たぶん無いと思います。
引用返信 編集キー/
■36925 / inTopicNo.3)  Re[2]: C# 、TCP通信処理時の受信待ち処理について
□投稿者/ なちゃ (290回)-(2009/06/10(Wed) 08:55:30)
ちなみに、StreamReaderはどんな感じに使ってますか?
というか受信部分全体の方がいいですが。

引用返信 編集キー/
■36931 / inTopicNo.4)  Re[1]: C# 、TCP通信処理時の受信待ち処理について
□投稿者/ オショウ (222回)-(2009/06/10(Wed) 10:10:07)
> TCP通信の処理は初めてなのですが、受信処理はブロックされますよね?

  ブロキング=同期通信 方式を採用されていると言うことですネ

  で、非ブロッキングを使いたい?と言うことですか?
  非ブロッキング=非同期通信

  http://codezine.jp/article/detail/22?p=1

  非同期通信のサンプルです。

  参考まで・・・

以上。
引用返信 編集キー/
■36933 / inTopicNo.5)  Re[2]: C# 、TCP通信処理時の受信待ち処理について
□投稿者/ なちゃ (291回)-(2009/06/10(Wed) 10:48:02)
No36931 (オショウ さん) に返信
>   ブロキング=同期通信 方式を採用されていると言うことですネ
>
>   で、非ブロッキングを使いたい?と言うことですか?

いや、違うと思いますよ、多分…
ブロッキングされる想定なのに、ブロッキングされない場合があるのか?という話だと思います。
※れいさんが書かれてるような話

引用返信 編集キー/
■36936 / inTopicNo.6)  Re[3]: C# 、TCP通信処理時の受信待ち処理について
□投稿者/ オショウ (223回)-(2009/06/10(Wed) 11:01:01)
2009/06/10(Wed) 11:02:10 編集(投稿者)

> いや、違うと思いますよ、多分…
> ブロッキングされる想定なのに、ブロッキングされない場合があるのか?という話だと思います。

  をを〜・・・
  FINパケット受け取ったら受信したかのように抜けて、受信データはなし・・・
  と言う状態はあります。

  で、その場合、即コネクションを破棄・クローズして、再度コネクトに行く動作
  を行う・・・と言う必要があると思います。

※ ブロッキングでも非ブロッキングでも、FINを受信した際の挙動については
  詳しく書いてないので、ブロッキングしているのに抜けてくる・・・と言う
  原因が解らないと言うカキコは過去多かったように・・・

  如何でしょう?

以上。
引用返信 編集キー/
■36962 / inTopicNo.7)  Re[4]: C# 、TCP通信処理時の受信待ち処理について
□投稿者/ れい (847回)-(2009/06/10(Wed) 15:42:08)
No36936 (オショウ さん) に返信
>FINパケット受け取ったら受信したかのように抜けて、受信データはなし・・・
>と言う状態はあります。
これは前投稿で私が言った「Readで待機している際にStreamが閉じた場合も同様に0が返り、一文字も読めないのにブロックが解除されます。」
に相当します。

>   で、その場合、即コネクションを破棄・クローズして、再度コネクトに行く動作
>   を行う・・・と言う必要があると思います。

それは時と場合によりけりです。
再接続する必要があることの方が少ないと思います。

>   如何でしょう?

ですが、
> Readerが反応する事があるのでしょうか?
とあるので、たぶん関係ありません。

TCPレベルの話ではなく、StreamReaderが戻るかどうかの話でしょう。
引用返信 編集キー/
■36993 / inTopicNo.8)  Re[5]: C# 、TCP通信処理時の受信待ち処理について
□投稿者/ non (7回)-(2009/06/11(Thu) 02:31:11)
この掲示板を利用するのは初めてですが、1日しか経っていないのにいくつものアドバイスをいただいてびっくりです。
とりあえず説明が曖昧だったかもしれませんので整理します。

private void GetResponce()
{
while(true)
{
m_ServerResponse.Add(reader.ReadLine());
}
}

上記の関数を別スレッドにし、TCPソケットのストリームからメッセージを読み取っています。
基本的には無限ループの単純なスレッドで、ストリームリーダー(private StreamReader reader)で読んだものを汎用リスト変数(private List<string> m_ServerResponse)に格納するのみです。
(ロック他いくつかの処理の記述は煩雑になるので省略しました)

大元のスレッドでは別のインターバルタイマーでこのリストの内容を読み、終わった内容は破棄する・・というのが全体の概要です。
処理自体は正しく動いているようなのですが、問題なのは、ReadLineは何かを受信するまでブロックされると思ったのですが、
たまに何も入っていないItem(Item自体がNull)が混ざっているようなのです。

そこで例外が発生したあとでそれを無視して処理を続行した事はないのですが、
もしかしたらいただいたアドバイスの中にあった様に、TCPのコネクション(当然streamも)が閉じてしまっているのかもしれませんね。。
この現象はたまにしか発生しないのですが、しばらくまわして試してみます。





引用返信 編集キー/
■36995 / inTopicNo.9)  Re[6]: C# 、TCP通信処理時の受信待ち処理について
□投稿者/ れい (849回)-(2009/06/11(Thu) 03:30:56)
No36993 (non さん) に返信
> この現象はたまにしか発生しないのですが、しばらくまわして試してみます。

なら受信接続がきれたのでしょうね。
サーバーが接続を閉じたか、タイムアウトになったか。

http://msdn.microsoft.com/ja-jp/library/system.io.streamreader.readline(VS.80).aspx
にあるように、ストリームの末尾になった時=接続が切れた時のみnullが返るはずです。

引用返信 編集キー/
■37047 / inTopicNo.10)  Re[7]: C# 、TCP通信処理時の受信待ち処理について
□投稿者/ non (9回)-(2009/06/11(Thu) 21:57:21)
No36995 (れい さん) に返信

> なら受信接続がきれたのでしょうね。
> サーバーが接続を閉じたか、タイムアウトになったか。
>
> http://msdn.microsoft.com/ja-jp/library/system.io.streamreader.readline(VS.80).aspx
> にあるように、ストリームの末尾になった時=接続が切れた時のみnullが返るはずです。
>

不具合がおきるまで待って詳細を調べてみたのですが、御指摘のとおりTCPの接続自体が閉じ、結果ストリームの読み込みでnullが返っていたようです。
ストリーム読み込みの方ばかりに目が行き根本をチェックしていませんでした。。
エラーリカバリー含め全体の処理を見なおしてみます。
ありがとうございました。


解決済み
引用返信 編集キー/


トピック内ページ移動 / << 0 >>

このトピックに書きこむ

過去ログには書き込み不可

管理者用

- Child Tree -