• 締切済み

C# UDPで大きなサイズのファイルを送信するには

C# UDPで大きなサイズのファイルを送信するには いつもお世話になっております。 UdpClientでの通信に挑戦しているのですが、ファイルを送信する段階になって詰まっています。 2MBほどあるファイルを送受信したいのですが、一度には送れないので分割して送信しようとしています。 ところが、分割すると上手くいきません・・・ 現在32767byteずつ送信しているのですが、32800byteなどのテキストファイルは2つに分割されて上手く送信できたのですが 実際に2MBほどあるファイルを送信してみると、送信はしてても受信ができていません。 受信できたのは2つほどで、分割されたデータのほとんどがどこかへ行ってしまったみたいです。 そこで質問です。 (1)考えられる原因、対処法はありますか? (2)UDPで大きいサイズのファイルを送受信する場合、通常どうしていますか? わかる方がいましたらお願いします。

  • tasoh
  • お礼率87% (65/74)

みんなの回答

  • Yorisin
  • ベストアンサー率54% (364/663)
回答No.3

先にも出ていますが、送信手順を考えた方が良いですね。 TCP/IP, UDP/IPはデータが[確実に届くこと]はそもそも担保されていないので 上位層でカバーする必要があります。 通常のデータ通信では ・分割したデータにシーケンス番号(データの順序)を振り当てる ・シーケンス番号ごとにACKを返し、届いたことを送信側に伝える ・受信側は届いたデータをシーケンス番号の順に再度置き換える  (歯抜けでデータが来たときに、送信側から再送要求する場合もある) ・送信側に一定期間ACKが返ってこない場合、再送要求があった場合は  該当のデータを再度送信する ・一定期間で処理が完了しない場合はタイムアウトとして終了する といったシーケンスで通信を行います。 (初期段階のハンドシェイクは省略) ともかく、データが伝送路で破棄されることを前提に考え、 送信側では再送の仕組みを、受信側ではデータの再構築の仕組みを考えるべきでしょう。 なお、FTP通信はデータ部分はUDPを組み合わせているので、 参考にすると良いでしょう。 とりあえず ・送信側には受信データに対するACK処理  順序が入れ替わった場合の再組立処理 ・受信側にはACKなしの場合の再送処理 を追加してみてはどうでしょうか? あと、可能性は低いですが、データが化けていたり送信できていないとか? パケットをキャプチャしてネットワーク上に送信されているか、 また受信されているか(途中で破棄されていないか)、 期待するデータであるかなども確認して置いた方が良いかもしれません。

  • YUI_AI
  • ベストアンサー率45% (303/661)
回答No.2

UDPの場合は、エラー時の再送、パケットの不達にも対応していないので、その処理を行う様にしないといけません。 ※簡単に言うと送信プロトコルを作ることになります。 例 1.送信元よりデータを送信(1パケット目)※受信側からの応答待ちに入る 2.受信元がデータを受けた時点で応答パケットを返信 ※ACK、NAKなのの応答コード   ※一定期間受信しない場合はパケットロスと判断してNAKを送信等の対応が必要 3.送信元が応答コードを判断して現パケットを再送するか次パケットを送信するか判断を行い、対応パケットを送信する。※応答待ちに入る 2.~3.を全データ送信完了まで繰り返す 単純に書いてますが、各パケットにパリティコードを追加する等、データの整合性を保つ必要もあると思います。 これが面倒であればTCPでの送信に切り替えた方が良いかと思います。

  • chie65535
  • ベストアンサー率43% (8526/19383)
回答No.1

「送った順に届くとは限らない」ので「順番に届くと思って受信」すると「分割されたデータのほとんどがどこかへ行ってしま」う事があります。 例えば「1番が来たから次は2番の筈。2番以外が来たら無視」とかって処理をすると「分割されたデータのほとんどを自分で捨ててしまう」ことになります。 パケットの到達順は「不定」なので「1番、3番、4番、2番、5番…」と言う順で届く可能性もあります。 この時に「1番が来たから次は2番の筈。2番以外が来たら無視」すれば、3、4番は消えて無くなります。 その後に来た2番だけは続いて受信されますが、3番は「既に捨てている」ので、もう2度と届きません。 3番が届く事は「永久にない」ですから、3番以降のブロックは「全部、捨てられ」ます。 結果として「受信できたのは2つほどで、分割されたデータのほとんどがどこかへ行ってしま」う事になります。

関連するQ&A

  • winsockを使ったTCP及びUDP通信について

    今回winsockを使った通信プログラムを組む事になったのですが、わからない点が多々ありましたので、どなたかご教授頂けると大変ありがたいです。 1. TCP通信において、送信側が"Hoge" "Fuga"と2回sendした際、受信側でrecvすると"Ho" "geFu" "ga"と3回受信する可能性があると認識しているのですが、これは正しいでしょうか? (到着する順序は保証されるが、recvする際に送信側がどのようにsendしたかは考慮されない) 2. UDP通信においては、上記のような現象は起きないと認識しているのですが、これは正しいでしょうか? (UDP通信では、2回sendすれば2回以上はrecvしない。パケットの破棄はあっても、分割はない) 3. もしUDP通信でも上記のような現象が起きる場合、到着順序の保証がされないという観点から、recvした際に"Ho" "ga" "geFu"と受信する事はあり得るのでしょうか? 4. 2が正しい前提での話です。UDP通信では、MTUを超えた場合、自動でパケットが分割されると聞きました。プログラムを組む際、これは意識しないといけないのでしょうか? (MTUが1500Byteの場合、UDPで2000Byteをsendすると、recvで1500,500と2回受信する?) 以上の4点です。 どなたかご存知の方いらっしゃいましたら、是非ご教授ください。

  • UDPの信頼性について

    UDPでは、信頼性のない通信プロトコルとされていますが、あるノード内の2つのプログラム間でUDPを使用した通信(ローカル通信)をした場合も、信頼性がない通信となるのでしょうか? ここでいう信頼性とは下記を意味しています。 ・ 送信した順序で、受信側が受信する。 ・ 送信したメッセージを、1つも失うことなく受信側で受信できる。

  • UDPで受信スループットを測定

    Javaを使って通信のプログラムを勉強しています。 UDP通信のスループットを測定するプログラムを作成しています。 送信側で5242880バイトを128回に分割して送信して、 受信側でそれらのパケットを受信する時間を計測するプログラムを 作りたいのですが、受信側でどのタイミングで受信処理を止めるのかがわかりません。 start = System.currentTimeMillis(); for(;;){   socket.receive(RecvPacket);   if(ループを抜ける条件)     break; } stop = System.currentTimeMillis(); で受信し続けて、受信するパケットがなくなったらループを抜けるというように考えました。 UDPでは送信されたパケットがすべて届くという保証はないので、 128回受信したらループを抜けるというようにできないので、困っています。 届いたパケットの数も数えて到達率も計算したいです。 受信が終わったら、ループを抜けるというようにしたいのですが、 どうすればよいでしょうか?

    • ベストアンサー
    • Java
  • 【Yahoo!メール】添付ファイルの送受信(最大ファイルサイズ)

    【Yahoo!メール】添付ファイルの送受信(最大ファイルサイズ) Yahoo!メールで添付ファイルを送受信する際に、 ファイルサイズに関して制限はありますか? 5MB以上は送信できない、10MB以上は受信できない等 よろしくお願いします。

  • UDPソケット通信におけるデータパケット

    UDPソケット通信をする際、受信データサイズとして考慮するべきサイズはアプリサイズとUDPヘッダー(8バイト)としてソケットオプションで受信バッファサイズを増加させたのですが、予想より受信できるパケット数が少ないです。 例) 1パケットのアプリサイズを10バイトしUDPヘッダーも考慮して実際1パケットあたり18バイトとして、最大5パケット受け取れるようにソケットオプションで アプリサイズ(10バイト)× UDPヘッダー(8バイト)×パケット数(5) 上記のように設定したのですが、実際5パケットも受信できませんでした。 上記のほかにIPヘッダーなども考慮しなければならないのでしょうか? 開発環境:solaris8 C言語

  • WinsockによるUDP通信にて

    WinsockでUDP通信を行うプログラムを作っているのですが、 原因不明の問題が発生していて困っています。 通信手順は以下のとおりです。 (1) クライアントからサーバへ要求パケット送信 (2) 要求パケットを受け取ったサーバは、クライアントへACKを送信 (3) サーバが要求に対する応答パケットをクライアントへ送信 (4) 応答パケットを受け取ったクライアントは、サーバへACKを送信 クライアント-サーバ間でやりとりするデータは最大で992バイト、 それ以上になる場合は、分割して送信します。 パケットの分割が発生しない場合は、(1)~(3)がパケットの損失もなく通信できるのですが、 パケットの分割が発生する場合には、2回目以降の(4)のパケットがクライアントに届きません。再現率は今のところ100%です。 クライアント側のselect関数でもソケットを検出しません。 たしかにUDPは信頼性が低いですが、パケット分割が発生しないパターンでは100%届くので、UDPの仕様とは関係ないような気がします。 原因がさっぱりわからないので、アドバイスをお願いいたします。 ちなみに、クライアント、サーバともに同一端末内にあります(双方がループバックアドレスに対してパケットを送信)が、 これはテスト段階だからであって、本来はそれぞれ別々の端末で動作します。

  • ファイルサイズの転送

    javaのファイルサイズの転送で困っています。 最初にファイルサイズを転送し、あらかじめ受信サイズを知らせておきたいのですが。。。うまくいきません。 送信側では最初にファイルサイズ4バイト(intサイズ)送信し、サイズを書き込む。 受信側では4バイト読み込み、ファイルサイズ分のバッファを用意する。 どうすれば出来るでしょうか。おねがいします。

    • ベストアンサー
    • Java
  • UDPプログラム、データの送受信

    javaを使って通信の勉強をしています。 UDPを用いた通信のプログラムを作成しています。 送信側では、次のようにして送信したいバイト数を分割して送信しています。 BUF_MAX = 40960; DatagramSocket socket = new DatagramSocket(); // data分のバイトデータを分割して送信する。 int part = 5242880 / BUF_MAX; // 分割して送信する回数 send_start = System.nanoTime(); for(int i = 0;i < part;i++){   byte[] buf = new byte[BUF_MAX];   buf[0] = (byte)i;   DatagramPacket sendPacket = new DatagramPacket(buf,BUF_MAX,serverAddress,servPort);   total += BUF_MAX;   // 指定したバイト数を送信する。   try{     socket.send(sendPacket);   }catch(IOException e){     System.out.println(e);   } } System.out.println(total); このようにしています。 こうする理由は、5242880バイトのデータを128回に分割して送信して、 受信側で受信したパケットの最初の文字を見て、何個目のパケットが届いていないかを確認するためです。 受信側でこれらのデータを受信する方法を考えているのですが、どうすればよいか分かりません。 receive(packet)で受信するのは知っています。 送信された複数のデータを受信するのに、 for(int i = 0;i < 128; i++){  receive(packet); } というようにするのでしょうか?このようにすると、 このループを抜けることができません。それは、パケットが通信途中で紛失するため、128回受信しないからだとおもいます。 受信しなくなったらループを抜けるというようにすればよいとおもいますが、その方法が分かりません。 どなたかアドバイスをいただけないでしょうか?お願いします。

    • ベストアンサー
    • Java
  • Winsockを利用した単純なファイル送信プログラムについて

    こんばんは。 何度もこの掲示板を利用させていただいている者です。 WinsockのUDPを用いて簡単なファイル送信プログラムを作っています。UDPを使わずに、TCPを使用したほうが良いのでは?とのご指摘をいただきましたが、まずは、UDPを利用した単純なファイル送信プログラムを作ってみたいと思っています。 しかし、送信側から受信側へファイルがうまく受信できていません。もしかしたら、送信側自体がきちんと送信できていないのかもしれません。 以下にそのプログラムの概要と内容を示します。 [概要] 送信側→受信側にUDPを用いて、送信側にあるjpegまたはmpegファイルを送信し、受信側でファイルを開く。 [プログラム概要] ・送信側 ファイルポインタを用いてファイルオープン fread関数とsendto関数を用いて1024バイトずつ送信 ・受信側 ファイルポインタを用いてファイルオープン whileの無限ループ内に、recvfrom関数とfwrite関数を用いて送信側からのデータを受信 [プログラムの内容] ・送信側 printf("読み込み用ファイルを入力して下さい:"); scanf("%s",fname); if((fp = fopen(fname,"rb")) == NULL){ printf("入力ファイルをオープンできない。\n"); exit(1); } char send_buf[1025]; int n; while(n = fread(send_buf,1,1024,fp) != -1){ sendto(theSocket,send_buf,n,0,(LPSOCKADDR)&saServer,sizeof(struct sockaddr)); } ・受信側 char Recv_buf[1025]; char size; SOCKADDR_IN saClient; while(1){ size = recvfrom(theSocket,Recv_buf,1024,0,(LPSOCKADDR)&saClient,&nLen); fwrite(Recv_buf,size,1,fp); } ご指摘またはご教授をいただけたらと思います。 よろしくお願いします。

  • UDPパケットの分割について

    こんにちは。 現在、クライアント&サーバの通信プログラムを作成しています。 クライアントがサーバに接続しにいく際、サーバの待ち受けポートにクライアントが UDPでブロードキャストしています。 その際、クライアントの情報もUDPに乗せて、送信しています。 ここで、問題なのですが、ネットワークモニタで通信データを見てみると、 クライアントから送信するUDPデータが1500バイト?を超えると、UDPパケットの分割が行われ、 2つめのデータが、UDPではなく、IPで送信されています。 しかも、2つめのIPのパケットがサーバ側に届くケースと届かないケースがあるように見受けられます。 (環境の違いかもしれません。) 2つめのパケット破棄は破棄が起こる環境では必ず起きます。 破棄が起きない環境では一回も起こりません。 スイッチ、NIC等で、破棄することってあるのでしょうか? ネットワーク上の問題っぽいので、OSの違い(Win2K pro,Win2k advanced server) などには関係ないですよね? どなたが、ご存知の方がおられましたらご教授願います。