こんばんは。
何度もこの掲示板を利用させていただいている者です。
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);
}
ご指摘またはご教授をいただけたらと思います。
よろしくお願いします。
No.4ベストアンサー
- 回答日時:
while(n = fread(send_buf,1,1024,fp) != -1){
ですが、freadはファイル終了時、0を返します。
-1が返ることはありません。
while((n = fread(send_buf,1,1024,fp)) != 0){
としてください。
#3のかたの指摘は、自分で考えるとして、
とりあえず、上記のようにしてください。
また、
while()}
sendto()...
}
のなかで、nの値を印字してみては、いかがですか。
そうすれば、何文字読めているかも確認できます。
この回答への補足
書き込みありがとうございます。
<引用文>
while()}
sendto()...
}
のなかで、nの値を印字してみては、いかがですか。
そうすれば、何文字読めているかも確認できます。
-------------------------------------------------
そこで以下のように記述してみました。
[送信側]
char send_buf[1025];
char send[4] = "end";
int n;
int Num_n = 0;
while((n = fread(send_buf,1,1024,fp)) != 0){
Num_n++;
printf("n:%s\t",send_buf);
sendto(theSocket,send_buf,n,0,(LPSOCKADDR)&saServer,sizeof(struct sockaddr));
}
printf("nの数:%d\n",Num_n);
sendto(theSocket,send,strlen("end"),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);
//エラーではじかれる部分
if(!strcmp(size,"end")) break;
}
printf("ファイル受信完了\n");
送信側PCに、
printf("n:%s\t",send_buf)
にて、画面出力させたところテキストファイル内の文字列が表示されました。
次の問題なのですが、
送信側のwhileループから抜けた時点で「end」を送信し、受信側で「end」を受信したら無限ループから抜けるようにしてみたのですが、受信側の記述方法が分かりません。
上記の受信側プログラムに
if(!strcmp(size,"end")) break;
と記述したのですが、エラーのためできませんでした。
よろしくお願いします。
No.7
- 回答日時:
>ワイヤレス環境下であり、かつUDPを使用しているため、パケットが送信側から受信側へ行く途中でロスしてしまっているのだと思っています・・・・。
>大変勉強になっているのですが、ロス率をできるだけ回避する方法とかあるのでしょうか?
UDPはもともとロスすることを前提としたプロトコルなので、やむを得ないと考えます。これを避けるには、TCP/IPにより、送受信を行う方法しかありません。
UPDを使用し、かつロスしない仕組みをアプリケーションで作るなら、以下のようになります。(1つの例として)
1)送り側は、データの先頭にデータの番号を付加して送ります。データの番号は、int型整数(4バイト)が、妥当でしょう。これを1からの連番で、送ります。
2)受信側は、この番号を監視します。従って、純粋なデータは、受信したものから、この番号を削除したものになります。
3)受信側では、データを受信する都度、受信した証として、この番号を送信元へ送ります。
4)送信側は、自分が送った番号が、受信側から戻ったことを確認して、次のデータを送ります。
上記のように、UDPでデータのロストを防ぐためには、大変な労力が発生します。もともと、ロストしても良い場合に、UDPを使用します。従って、他の方も言われてますように、TCP/IPで送信を行うのが、最も現実的な解決の方法になります。
いろいろ教えてくださり、ありがとうございました。
大変勉強になりました。
これからもプログラミング、ネットワークの学習に精を出していきたいと思っています。
また質問したときには、よろしくお願いします。
No.6
- 回答日時:
>3Mバイト程度のmpegファイルまたは、150Kバイト程度のjpegファイルを送信してみたところ、送信はできていると思うのですが、うまく受信できません。
どのように、うまくできていないのですか?
1)「データ受信しました」は、受信側で表示されましたか?
2)「データ受信しました」は、送信側で表示されましたか?(データ送信しましたの間違い?)
3)受信側でファイルに書いた内容と、送信側のファイルの内容は一致していますか?
この回答への補足
書き込みありがとうございます。
<引用文>
1)「データ受信しました」は、受信側で表示されましたか?
2)「データ受信しました」は、送信側で表示されましたか?(データ送信しましたの間違い?)
3)受信側でファイルに書いた内容と、送信側のファイルの内容は一致していますか?
申し訳ありません。きちんと、送信データを受信することができました。受信側の「データ受信しました」もきちんと表示されました。
ありがとうございました。
実は、今まで、一台の端末で送信側と受信側のプログラムを走らせてデータ送信と受信を確かめていました。
さきほど端末2台を用いて、ワイヤレス環境下でのアドホック通信を試みたところ、3Mバイトのmpegファイルを送信したところ、受信側では1Mバイト程度のファイルになっていました。また、jpegファイルのファイル容量によって、受信側の「データ受信しました」が表示されず「Ctrl + C」にて強制終了しています。
ワイヤレス環境下であり、かつUDPを使用しているため、パケットが送信側から受信側へ行く途中でロスしてしまっているのだと思っています・・・・。
大変勉強になっているのですが、ロス率をできるだけ回避する方法とかあるのでしょうか?
たびたびすみません。
よろしくおねがいします。
No.5
- 回答日時:
受信側ですが、
char size;を
int size;にしてください。char型では127バイトまでしか、対応できません。(300バイトがくると、動作がおかしくなります)
問題の場所を、以下のようにしてください。
if (size == 3){
if (memcmp(Recv_buf,"end",3) == 0) break;
}
とします。
これは、受信したサイズが3バイトかつ、受信した文字が
"end"ならbreakするという意味です。
recvfromの戻り値は、受信したデータではなく、受信したデータのサイズですから、その点を間違えないでください。
この回答への補足
書き込みありがとうございます。
ご提示して下さいました、プログラムを以下の場所に挿入したところ、テキストファイルを送信側から受信側へと送信することができました。
ありがとうございます。
また質問なのですが、
3Mバイト程度のmpegファイルまたは、150Kバイト程度のjpegファイルを送信してみたところ、送信はできていると思うのですが、うまく受信できません。ファイルの最後を意味するために付け加えた「end」では、mpegやjpegファイルに対しては効果がないのでしょうか?
[送信側]
char send_buf[1025];
char send[4];
int n;
int Num_n = 0;
strcpy(send, "end");
while((n = fread(send_buf,1,1024,fp)) != 0){
Num_n++;
printf("n:%dバイト\t",n);
sendto(theSocket,send_buf,n,0,(LPSOCKADDR)&saServer,sizeof(struct sockaddr));
}
printf("nの数:%d\n",Num_n);
sendto(theSocket,send,strlen(send),0,(LPSOCKADDR)&saServer,sizeof(struct sockaddr));
printf("データ受信しました\n");
fclose(fp);
closesocket(theSocket);
[受信側]
char Recv_buf[1025];
int size;
SOCKADDR_IN saClient;
while(1){
size = recvfrom(theSocket,Recv_buf,1024,0,(LPSOCKADDR)&saClient,&nLen);
fwrite(Recv_buf,size,1,fp);
if (size == 3){
if (memcmp(Recv_buf,"end",3) == 0) break;
}
}
printf("データ受信しました\n");
fclose(fp);
closesocket(theSocket);
よい方法がありましたら、教えていただけないでしょうか?よろしくお願いします。
No.2
- 回答日時:
では、ファイルを読み込んで送信するのを止めて、単純にsendtoを行うだけにしてテストしてみてください。
1回のsendtoだけなら成功しますか?・・・というふうに、単純なものから順番に調べていくのが、普通の調べ方です。
No.1
- 回答日時:
1. どのように、うまく受信できていないのですか。
ある程度のデータは受信側に届いているのですか、それとも何も届いていないのですか。送信側は正常終了するのですか、何かエラーが発生するのですか。2. 一度に送信するデータの量を128バイトに減らすと、状況はどう変わりますか。
この回答への補足
書き込みありがとうございます。
>1. どのように、うまく受信できていないのですか。 ある程度のデータは受信側に届いているのですか、それとも何も届いていないのですか。送信側は正常終了するのですか、何かエラーが発生するのですか。
「hoge」と記述したテキストファイルを送ってみたところ、受信側では、「hoge」の頭文字である「h」がたくさん表示されます。
送信側は、while(n = fread(send_buf,1,128,fp) != -1)から抜けると「データ送信しました」と表示するようにしましたが、表示されません。そこで「ctrl + C」で強制的に終了しています。また、受信側も同様に強制終了しています。
2.128バイトに減らしても1の内容と変わりませんでした。
よろしくお願いします。
お探しのQ&Aが見つからない時は、教えて!gooで質問しましょう!
似たような質問が見つかりました
- PHP どうして送信されないのでしょうか? 1 2022/12/09 05:23
- PHP a href リンクタグでだけで 送信が できちゃっています。 1 2022/04/18 04:25
- Visual Basic(VBA) エクセルのマクロを使ってメールを送る方法について教えてください 2 2022/03/29 01:36
- PHP htmlspecialcharsが機能していないです。 バグですか? 1 2022/04/05 01:22
- C言語・C++・C# このプログラミング誰か教えてくれませんか 1 2022/06/02 15:27
- Visual Basic(VBA) Excel-VBAでのファイルの開き方 4 2023/02/14 11:01
- Outlook(アウトルック) w10からw11にバージョンアップ。アウトルックがクラウドと連携…そのためか、連絡先が消失!! 3 2023/05/09 18:34
- Windows 8 メール送信、zipファイル PDFについて 回答お願いいたします。 Windows8 メールはサクラ 1 2022/05/12 17:49
- Excel(エクセル) アンケート集計用VBAについて教えて下さい。 約100人にアンケート内容が入ったExcelファイルを 1 2022/07/27 13:12
- C言語・C++・C# TCP/IP通信時のサーバーからの受信 2 2022/11/23 09:11
関連するカテゴリからQ&Aを探す
おすすめ情報
デイリーランキングこのカテゴリの人気デイリーQ&Aランキング
-
Outlookの「受信日時」「件名」...
-
TCP/IP のパケットの分断と結合...
-
VC++メッセージの送受信につい...
-
「TCPは全二重可能」の意味
-
ネットワークでの受信バイト数
-
PIC-PCシリアル通信プログラム
-
Outlookの「受信日時」「送信者...
-
PC98で232c送信winndowで受信で...
-
ASP.NET C#でPOST受信
-
recv関数の戻り値について
-
パソコンに詳しい方教えて下さ...
-
Windows上のファイル操作の履歴...
-
バッチファイルでディレクトリ...
-
別のフォルダにファイルを移動...
-
Chromeリモートデスクトップで...
-
Lhaplusが発したと、みられるエ...
-
フォルダ内ファイルの自動削除化
-
バックアップの用語
-
Zipファイルをエクセルに指定変...
-
en_US.UTF-8ロケールってどのPO...
マンスリーランキングこのカテゴリの人気マンスリーQ&Aランキング
-
Outlookの「受信日時」「件名」...
-
Outlookの「受信日時」「送信者...
-
TCP/IP のパケットの分断と結合...
-
シリアル通信時のデータ受信方法
-
UDP受信時の通信異常検知について
-
RS232cを用いた送信プログラム
-
C#にてCTI。RS232Cの受信と送信...
-
VC++メッセージの送受信につい...
-
DHCPOFFERの受信について
-
TCPのプログラミングで質問…と...
-
ネットワークでの受信バイト数
-
パケット受信 recvfrom( )につ...
-
ASP.NET C#でPOST受信
-
recv関数の戻り値について
-
TCPでパケットロス?
-
PC98で232c送信winndowで受信で...
-
VB2005でTCP/IPソケット通信で...
-
「TCPは全二重可能」の意味
-
vb2005でUDP受信時にフォームが...
-
VBのMSCommコントロールを使っ...
おすすめ情報