C# UdpClient 分割送信方法
- 評価
- クリップ 1
- VIEW 9,338
C#でUdpClientを使い、0.5秒毎に300KB程のデータを送信するプログラムを作っているのですが、UDPではTCPと違い自動で分割?をしてくれないみたいです。
一回で送ろうとするとバッファが足りないとerrorが出ました。
分割して送信する方法を調べてみたのですが、このように1回で送信しているSampleしか出てきませんでした。
試しにこのようなコードを書いてみましたが効果がありませんでした。
udp.Client.SendBufferSize = 300000;
Udpでの分割送信方法を教えてください
<追記>
int size = sendBytes.Length;
int size2 = 0;
byte[] data = new byte[16000];
while (size > 16000)
{
Array.Copy(sendBytes, size2, data, 0, 8000);
udp.Send(data, data.Length);
size2 += 8001;
size -= 8000;
}
Array.Copy(sendBytes, size2, data, 0, sendBytes.Length);
udp.Send(data, data.Length);
このような感じで送信コードを書いてみたのですが、分割して送られてくるByte配列を連結させる方法がわからないです。
-
気になる質問をクリップする
クリップした質問は、後からいつでもマイページで確認できます。
またクリップした質問に回答があった際、通知やメールを受け取ることができます。
クリップを取り消します
-
良い質問の評価を上げる
以下のような質問は評価を上げましょう
- 質問内容が明確
- 自分も答えを知りたい
- 質問者以外のユーザにも役立つ
評価が高い質問は、TOPページの「注目」タブのフィードに表示されやすくなります。
質問の評価を上げたことを取り消します
-
評価を下げられる数の上限に達しました
評価を下げることができません
- 1日5回まで評価を下げられます
- 1日に1ユーザに対して2回まで評価を下げられます
質問の評価を下げる
teratailでは下記のような質問を「具体的に困っていることがない質問」、「サイトポリシーに違反する質問」と定義し、推奨していません。
- プログラミングに関係のない質問
- やってほしいことだけを記載した丸投げの質問
- 問題・課題が含まれていない質問
- 意図的に内容が抹消された質問
- 過去に投稿した質問と同じ内容の質問
- 広告と受け取られるような投稿
評価が下がると、TOPページの「アクティブ」「注目」タブのフィードに表示されにくくなります。
質問の評価を下げたことを取り消します
この機能は開放されていません
評価を下げる条件を満たしてません
質問の評価を下げる機能の利用条件
この機能を利用するためには、以下の事項を行う必要があります。
- 質問回答など一定の行動
-
メールアドレスの認証
メールアドレスの認証
-
質問評価に関するヘルプページの閲覧
質問評価に関するヘルプページの閲覧
checkベストアンサー
+2
TcpClientの質問の続きとして、いくつかアドバイスさせていただきますね。
まずは、分割送信のコード修正案を。
送信コード修正案
byte[] data = new byte[1024];
int rest = sendBytes.Length;
while (rest > 0)
{
int size = Math.Min(rest, 1024);
Array.Copy(sendBytes, sendBytes.Length - rest, data, 0, size);
udp.Send(data, size);
rest -= size;
}
TCPとの違いについて
TCPとUDPではいろいろと違いがありますが、問題となっている処理に深く関係することとして、次の違いを意識してコードを書く必要があります。
- UDP はデータ境界が保証されている(一度のsend()/sendto()で送信したデータが相手側で一度のrecv()/recvfrom()で受信されることが保証されているという意味です。)ただし以下のポイントに注意!
- UDP は送信したデータが届かないことがある。(データが破棄されたことが送信側/受信側のどちらのアプリケーションにもまったく通知されないことがある。欠落したデータのリカバリー処理が必要な場合、アプリケーションに実装する。)
- UDP は送信したデータ順と受信されるデータ順が変わることがある。(送信データの順番を確認したり、入れ替わったデータ順を元の状態に復元する処理が必要な場合、アプリケーションに実装する。)
UDPの送信データ長について
UDP通信では一度に送信するデータ長は最大でも 500 バイトから 1300 バイト程度にするのが一般的です。何故なら、大きすぎるUDPデータは、IP層でのフラグメント分割を引き起こし、フラグメントが遺失し結果としてUDPデータが相手ノード側で破棄されるリスクを増大させるからです。
- (参考サイト) IPパケットの構造とIPフラグメンテーション
最後に
実現されようとしているシステムがどのようなものなのか解らないですが、データ送受信のコードの書き方をどうするかということの前に、システムとしてデータリカバリーの実装方法とデータの圧縮(本当に300KBのデータが全部必要なのかなど)、「回線品質の悪い状況」に関する動作保証範囲などについて改めて検討されるほうがよいかと思います。
投稿
-
回答の評価を上げる
以下のような回答は評価を上げましょう
- 正しい回答
- わかりやすい回答
- ためになる回答
評価が高い回答ほどページの上位に表示されます。
-
回答の評価を下げる
下記のような回答は推奨されていません。
- 間違っている回答
- 質問の回答になっていない投稿
- スパムや攻撃的な表現を用いた投稿
評価を下げる際はその理由を明確に伝え、適切な回答に修正してもらいましょう。
+2
TCP通信と違ってUDPの場合は全部自分で始末しなければならない,ということは理解されてると思います.
ちょっと今すぐにサンプルを提示することが出来ないのでアレですが,イメージとしては以下のようにお考えください.
1.分割するサイズは1度に送るサイズ-独自のヘッダサイズ
2.分割したデータの先頭(もしくは後ろでも結構ですが何処かに)荷物の順番を決める情報をのせる
3.受け取った側はその荷物の場所を考慮しながら配列にしまっていく
といった感じです.
たとえば,荷物が8個に分割されたとします.
(全データイメージ)
AAAABBBBCCCCDDDDEEEEFFFFGGGGHHHH
それぞれの荷物をおくる際にヘッダを付けます
受け取っている側は分割数も分からないので全体量を示すものもあったほうが良いかもしれないですね
0108AAAA (1/8の荷物)
0208BBBB
0308CCCC
:
0808HHHH (8/8の荷物)
パケットサイズはこの際規定として決めてある,としましょうか.
受け取った側はヘッダ部分を取り除いて復元していきます.
その際,分割総数と受け取ったヘッダ情報から「受け取ってない荷物がないか」を逐次チェックします.
(UDPは郵便事故が起こることを否定していません)
とりあえず,末端のパケット,もしくは一定時間の空きを見て,受け取ってない荷物があるならそれを再送する(受信側→送信側への)リクエストを起こします.
UDPは余分なヘッダがついてないので早い,と言われますが,荷物の管理はかならず必要ですので,本来の用途としては
1回データを見逃すくらいどうってこと無いよ!
というケースで使うのが普通です.したがって今回のように荷物の健全性を保証しなくてはならない場合,ある程度自分で管理する必要がある,ということは判って頂けるかと思います.
じゃあどうすればいいか?
TCPで分割送信したら良いんじゃないですかね?という提案です.
投稿
-
回答の評価を上げる
以下のような回答は評価を上げましょう
- 正しい回答
- わかりやすい回答
- ためになる回答
評価が高い回答ほどページの上位に表示されます。
-
回答の評価を下げる
下記のような回答は推奨されていません。
- 間違っている回答
- 質問の回答になっていない投稿
- スパムや攻撃的な表現を用いた投稿
評価を下げる際はその理由を明確に伝え、適切な回答に修正してもらいましょう。
0
ご質問の意図を勘違いしていたらすみません。
UDP通信なので、送信側、受信側ともどちらも実装されることだと思いますが、仕様上特に手順もなく送りつける(と言ったら語弊があるかもしれませんが)ので、分割したければ独自の分割手順を送信側・受信側に実装するしかないのではないかと思います。
投稿
-
回答の評価を上げる
以下のような回答は評価を上げましょう
- 正しい回答
- わかりやすい回答
- ためになる回答
評価が高い回答ほどページの上位に表示されます。
-
回答の評価を下げる
下記のような回答は推奨されていません。
- 間違っている回答
- 質問の回答になっていない投稿
- スパムや攻撃的な表現を用いた投稿
評価を下げる際はその理由を明確に伝え、適切な回答に修正してもらいましょう。
15分調べてもわからないことは、teratailで質問しよう!
- ただいまの回答率 88.36%
- 質問をまとめることで、思考を整理して素早く解決
- テンプレート機能で、簡単に質問をまとめられる
質問への追記・修正、ベストアンサー選択の依頼
tkanda
2016/04/20 19:47
300KBのデータは外部ファイルから読み込んだものですか?それともオンメモリで生成されたものですか?
それと、0.5秒ごとに送信しているデータは、すべて欠かせない仕様ですか?それとも、いくらか抜け落ちても(相手に届かなくても)かまわない性質のものですか?
sem2012sp_a
2016/04/20 19:51
300KBのデータはメモリから読み込んだものです。外部ファイルは一切使いません。
いくらか抜け落ちても構いません。