- ベストアンサー
Readメソッドが次の行に処理を渡すタイミング
C#ですが、Readメソッドを使ってバイト配列を 読み込むとき、次の処理に移るタイミングが よく分かりません(ソケットからデータを受ける時)。 例えば、JAVAなどのreadLine()などは、改行や、 EOFで、次の行に移ります。 Readは、このような、区切りが無いのでよく分かり ません。 0バイトで移るのかとも思いましたが、受信バイト数 を数えると、文字数以上のバイトはいっさい受信 されていないので、送信側で、自動で0バイトを つけているようでもありません。 それでも送信側で文字を送ると、その送信単位で 次の処理に移ってくれています。 送信から次の送信までの区切りは何で認識して いるのでしょうか(区切りがない以上、受信バッファ がいっぱいになるまで、待ってもよさそうですが)。 なにか分かる人がいましたらお願いします。
- みんなの回答 (2)
- 専門家の回答
質問者が選んだベストアンサー
C# はよく知らないので、私の知っている範囲での話になってしまいますけど、参考まで。。。 受信通知のタイミングは、「何か受信したら、その時点で通知する」と思います。 UDP であれば、送信側が Write したサイズ分受信したところでソケットから受信通知があがってくるので、そこで Read すればそのサイズ分のデータが受信できることになります。 MTU 以上のデータが Write された場合には、IP で UDP パケットの Fragment 分割処理が入ることになりますので、受信側では IP Reassemble 処理され、結果として送信側が Write したサイズ分受信することになります。 # UDP を使う上位プロトコルで、そんなに大きなサイズのデータを送るような # ものがあるのかどうかは知りませんけど。。。 TCP の場合、話がもう少々複雑になりますが、基本的には1パケットを受信したところで受信通知があがってくると思って良いと思います。 TCP では、MSS 単位でデータをパケット分割します。 ですので、送信側が MSS より大きなパケットを Write した場合、無条件で MSS 単位に分割されてしまいます。 そのような場合には、受信側は MSS 単位に分割された1パケット受信したところでソケットから受信通知があがってくることになります。 そこで Read すれば、当然そのサイズ分だけデータを受信することになります。 ただし、送信データをすべて受信したところで受信通知をあげるようにすることも可能です。 TCP では、受信データを一区切りまでソケットで保留しておくことが可能なんです。 # その区切りは送信側の TCP がつけることになります。 TCP では「ひとつのデータ」という概念はなく、あくまで連続したデータ (ストリームといいます) としてしか意識していません。 ですので、受信通知のタイミングは、1パケット受信のタイミングであるか、あるいは送信側がつけた区切りのタイミングであるか、いずれかでしかデータ受信通知をあげることができません。 受信バッファがいっぱいになったタイミングで受信通知をあげてしまうと、そのバッファに空きができるまでデータが受信できなくなります。 こうすると、効率的にもあまりよくないですよね? ちなみに、受信バッファがいっぱいになる前に、しきい値まで受信したら上位に通知するという仕組みを使っているものもありますけど、TCP ではそのような方式は使っていないですね。
その他の回答 (1)
- sha-girl
- ベストアンサー率52% (430/816)
C#というか一般的にソケット通信の話ですが 例えばSendで瞬間的に何度も文字列を送った場合 その文字列は受け取ったときに 連結する可能性があります。 また逆に一度に大量の文字列(例えば10000文字)とか 送った場合 Read時に分割する可能性があります。 その辺はOSのMTUの設定に依存します。 >区切りが無いのでよく分かりません。 つまり区切りになる文字を自分で定義するか、 サイズの情報も一緒に送るしかありません。
お礼
回答ありがとうございます。 自分で区切りを作るのですか。 やってみます。
お礼
回答ありがとうございます。 受信通知とか、パケットサイズとか、 参考になりました。 もう少しがんばってみます。