プロが教えるわが家の防犯対策術!

チャットプログラムではないのですが、チャットプログラムのソースが参考になると思いネットで調べて見ましたが見つからなかったので質問させていただきます。

したいのは、.rarなどの圧縮されたファイル(サイズはGB単位)の送信(TCP)です。

トータルのファイルサイズとファイル名をBYTE配列に書き込む
BYTE配列のサイズを送信後、BYTE配列を送信
(とりあえずここでトータルサイズを4MB(4×1024×1024)で割った商をQ、余りをRと置いておく)
ファイルをバイナリ読み込みモードで開く
受け取ったという合図を受け取ったらファイルの先頭から4MB読み込んでBYTE配列に入れて送信
受け取ったという合図を受け取ったら続きから4MB読み込んでBYTE配列に入れて送信
↑を先頭の分も合わせてQ回繰り返す。
受け取ったという合図を受け取ったら続きからRバイト読み込んでBYTE配列に入れて送信
ファイルを閉じる
としたのですが、

ファイルの先頭から4MBは送信できているようなのですが、そこから先に進みません。
具体的には、4MBの受信したという合図を送っても、send関数が-1を返すようです

プログラムは以下の通りです
Server

Winsockの設定やファイルのトータルサイズ云々なので略
listen( RecvSock, 5 );
fp = fopen( FileName, "rb" );

int TotalSend = 0;
int i = -1;
SendSock = accept(RecvSock, (struct sockaddr *)&Send, &len);//コメントアウトを外す場合はこれはコメントアウト
while(1)
{
//SendSock = accept(RecvSock, (struct sockaddr *)&Send, &len);
if( i == -1 )
{
send( SendSock, (char *)&FileSize, 4, 0 ); //↓の配列サイズを入れたBYTE配列
send( SendSock, (char *)Buff, Size, 0 );//トータルファイルサイズとファイル名
delete []Buff;//BYTE *Buff = new BYTE[FileSize]としたため
}

//フラグ受信
{
recv( SendSock, (char *)&i, 4, 0 );
}
if( i == Q )
{
fread( SendBuff, R, 1, fp );
while( TotalSend < R )
{
TotalSend += send( SendSock, (char *)&SendBuff[TotalSend], R-TotalSend, 0 );
}
} else if( i != -1 ) {
fread( SendBuff, SendSize, 1, fp );// SendSizeは4*1024*1024の値を#define
while( TotalSend < SendSize )
{
TotalSend += send( SendSock, (char *)&SendBuff[TotalSend], SendSize-TotalSend, 0 );
}
}
printf( "%d/%d\n", i, Q );

}

Client
//Winsockの設定やファイルのトータルサイズ云々なので略
FILE *fp = fopen( FileName, "ab" );
int Total = 0;
for( int i=0 ; i<=Q ; i++ )
{
//connect( Sock, (struct sockaddr *)&Addr, sizeof(Addr) );
int Error = FileRecv( Sock, i, Q, R, fp );
if( Error == -1 )
{
i--;//エラーが出るのでどこでエラーが出るのか見るために追加
} else {
printf( "%d/%d\n", i, Q );
}
}

int FileRecv( SOCKET Sock, int Flag, int Q, int R, FILE *fp )
{
//Winsockの設定をコメントアウト中。外した場合、引数のSOCKET Sockは消す
int Total = 0;
//フラグ送信
{
BYTE buff[4];
memmove( buff, &Flag, 4 );
int Error = send( Sock, (char *)buff, 4, 0 );
if( Error == -1)
{
return -1;
}
}

if( Flag == Q ){
Buff = new BYTE[R];
memset( Buff, 0, sizeof(Buff) );
while( Total < R )
{
Total += recv( Sock, (char *)&Buff[Total], R-Total, 0 );
}
fwrite( Buff, R, 1, fp );
delete []Buff;
} else {
Buff = new BYTE[SendSize];
memset( Buff, 0, sizeof(Buff) );
while( Total < SendSize )
{
Total += recv( Sock, (char *)&Buff[Total], SendSize-Total, 0 );
if( Total == -1 )
{
delete []Buff;
return -1;
}
}
fwrite( Buff, SendSize, 1, fp );
delete []Buff;
}
//closesocket(Sock);
// WSACleanup();
return 1;
}
毎回切断してもう一度接続しなおすようにしても(コメントアウトを外す)結果(エラー部)は変わりません。
どこが悪いのか見ていただけないでしょうか?

A 回答 (1件)

>Total += recv( Sock, (char *)&Buff[Total], SendSize-Total, 0 );


>if( Total == -1 )
>{
> delete []Buff;
> return -1;
>}

最初のパケット受信で失敗しない限り、エラー処理に入りません。
# エラーをず~~~~っと続ければそのうちはいりますけどね。
# 最初に100バイトrecv()出来た場合は、次にrecv()でエラーが101回になった時点でエラー処理に入れるようになります。

>int Error = send( Sock, (char *)buff, 4, 0 );
>if( Error == -1)
>{
> return -1;
>}

そのまま戻るんじゃなくて…せめてエラーの原因くらいは調べた方がいいのではないですか?
# recv()でもですが。

http://msdn.microsoft.com/en-us/library/windows/ …
で…SOCKET_ERRORが返されたらWSAGetLastError()でエラーの詳細が得られる。
となっています。
# -1ってマジックナンバーではなく、ちゃんとSOCKET_ERRORと記述するべきです。

>while( TotalSend < R )
>while( TotalSend < SendSize )
のループに入る時、それぞれの変数は適切に初期化されていますか?
# 例によって省略されているんでしょうけど。

双方でパケットキャプチャしてみて、想定通りにやりとりが行われていますか?
    • good
    • 0
この回答へのお礼

>while( TotalSend < R )
>while( TotalSend < SendSize )
のループに入る時、それぞれの変数は適切に初期化されていますか?
1回目のループでは初期化してますが、2回目以降が初期化されてないですね

int TotalSend = 0;
while(1)
{
と外に置いちゃったのが問題でしたね。
下らない質問にお手数をかけて申し訳ありませんでした。
おかげさまで解決です。
ありがとうございました

お礼日時:2012/03/21 13:42

お探しのQ&Aが見つからない時は、教えて!gooで質問しましょう!