- ベストアンサー
C# ソケット通信でデータ受信時の欠損について
- C#のSocket Classを使用してデータの送受信をするプログラムを作成していますが、非同期でデータを受信する際にデータの欠損が起きてしまう問題に悩んでいます。
- 現在の方法では、socket.BeginReceiveで受信開始し、受信時のコールバック関数の中でデータとサイズを取得し、再度socket.BeginReceiveで受信を続けていますが、この方法だとデータの一部が取りこぼされる可能性があります。
- 非同期でデータを受信する際に欠損なく受信する方法を知りたいです。別の方法などがあれば教えていただけると助かります。
- みんなの回答 (1)
- 専門家の回答
質問者が選んだベストアンサー
> 悩んでいるのは EndReceive から、 > 二回目のBeginReceiveまでの間に送られたデータを取りこぼしてしまうのではないかということです。 大丈夫よん。 プログラムがBeginReceive~EndReceiveでひとかたまりの受信データブロックを取得するのはあくまで「同じコンピューターのOSから」なので、その時「同じコンピューターのOS」は相手からのデータ送信をどんどこどんどこ受け付けている。 そもそも最初のBeginReceiveをしなくてもコネクションが確立された瞬間からOSは相手からデータを受け取っているのだ。 これは、次のようなイメージだ。 (1)あなたは一階に総合受付がある雑居ビルで仕事をしてる。(あなた=プログラム、総合受付=NIC) (2)一階の総合受付の中にあなた宛の郵便受けを置いたとする。(Socket#Listen、Socket#Accept) (3)郵便屋さんはそこにあなた宛の郵便をどんどこどんどこ持ってくる。 (4)あなたは部下に「郵便受けに何かないか見てこい。何もなかったら何か来るまでそこで見張ってろ。郵便が有ったら報告せよ。」という。(BeginReceive) (5)部下は降りていった時に郵便があればそのまま持って上がる。無ければ来るまで待つ。(コールバック) (6)あなたは部下から郵便を受け取って再び(4)を命じる。(EndReceive、AsyncState、BeginReceive) ここで、(3)と(4)~(6)は非同期にかつ独立して行われる。あなたや部下が郵便を取りに行こうが取りにいくまいが郵便屋さんは郵便を持ってきて便受けに入れるだけだ。具体的には(6)でEndReceiveとBegenReceiveの間に郵便屋さんが来たとしてもそれは便受けに郵便を入れるだけだ。 もちろん、あなたのプログラムが終了しようとしている時に郵便受けに溜まってるのにあなたが読まなかった郵便はプログラム終了(というかSocket#Close)とともにロストする。 TCPはこの郵便受けがぱんぱんになってしまったら郵便屋さん(というか郵便を送りつけてくる相手)にちょっと待って貰うとかそういう制御もしている。 イメージ的にはこんなイメージであなたはBeginReceiveとEndReceiveを実行するタイミングによる伝送データロストを気にする必要はない。もし本当にそんなちょっとしたタイミングの差でそんな事が起こるんならMicrosoftさんだってそんなコンポーネント作らんじゃろ。
お礼
ありがとうございます。 そのままでよさそうですね。 わかりやすいたとえで理解出来ました。