2010-12-08 7 views
0

私は2つのアプリケーションを持っています.1つはserver-appで、もう1つはclient-appです。どちらも同じコンピュータ上にあります.Clientには1つのボタンがあります。このボタンをクリックすると、クライアントはサーバーからファイルのダウンロードを開始します。 問題は、クライアント側ですべてのファイルが正常に受信された場合がありますが、クライアント側で最初のファイルのみが受信され、転送が中止されることがあります。下のコードに何か問題がありますか? any1私が間違っている場所を教えてくれる?私はこのようにコーディングするのが初めてです。 のご協力が大歓迎です。前もって感謝します。ここ はコードです:C#tcp socketクライアントサーバーで複数のファイルを転送する問題

ユーザーがクライアント上のボタンをクリックすると、クライアントがサーバからの要求のダウンロードファイルを送信します:

//client side 
sendRequest("requestFiles "); 

Serverは後にトークンrequestFiles

を受け取るダウンロードするには、クライアント用のファイルを準備します
// server side 
if (execmd == "requestFiles") 
{ 
    string[] fList = Directory.GetFiles(folderDir); 
    for (int i = 0; i < fList.Length; i++) 
    { 
     FileInfo fi = new FileInfo(fList[i]); 
     string[] mDesc = new string[3]; 
     mDesc[0] = fi.Name; 
     mDesc[1] = fi.Length.ToString(); 
     mDesc[2] = fi.FullName; 
     string fileSend = "CommitRequest " + fi.Name + " " + fi.Length.ToString() + " " + usID + " " + mName; 
     sendRequest(fileSend); 
     ClientDownloadingFromServer(mDesc[2], mDesc[1], sock); 
    } 
    sendComment("AllUpDone"); 
    continue; 
} 

各ファイルをアップロードする必要がある場合、サーバーはファイル(名前、サイズ)の詳細を含むCommitRequestトークンを送信します クライアントがCommitRequestを受け取ったとき:

クライアントで
//client side 
if (execmd == "CommitRequest") 
{ 
    //get file name and file size 
    downloadFileFromServer(sock); 
    continue; 
} 

方法downloadFileFromServer:サーバ側で

//client side 
private void downloadMapFromServer(Socket s) 
{   
    Socket sock = s; 
    //prepare directory rootDir to store file 
    System.IO.FileStream fout = new System.IO.FileStream(rootDir + "\\" + fileN, FileMode.Create, FileAccess.Write); 
    NetworkStream nfs = new NetworkStream(sock); 
    long size = int.Parse(fileS); 
    long rby = 0; 
    try 
    { 
     //loop till the Full bytes have been read 
     while (rby < size) 
     { 
      byte[] buffer = new byte[1024]; 
      //Read from the Network Stream 
      int i = nfs.Read(buffer, 0, buffer.Length); 
      fout.Write(buffer, 0, (int)i); 
      rby = rby + i; 
     } 
     fout.Close(); 
    } 
    catch (Exception ed) 
    { 
     Console.WriteLine("A Exception occured in file transfer" + ed.ToString()); 
     MessageBox.Show(ed.Message); 
    } 
} 

方法clientDownloadFromServer:

//server side 
void ClientDownloadingFromServer(string fiPath, string fiSize, Socket s) 
{ 
    string parm1 = fiPath; 
    string parm2 = fiSize; 
    try 
    { 
     FileInfo ftemp = new FileInfo(parm1); 
     long total=ftemp.Length; 
     long rdby=0 ; 
     int len=0 ; 
     byte[] buffed = new byte[1024] ; 
     // Open the file requested for download 
     System.IO.FileStream fin = new System.IO.FileStream(parm1,FileMode.Open , FileAccess.Read) ; 

     NetworkStream nfs = new NetworkStream(sock) ; 

     while(rdby < total && nfs.CanWrite) 
     { 
      //Read from the File (len contains the number of bytes read) 
      len =fin.Read(buffed,0,buffed.Length) ; 
      //Write the Bytes on the Socket 
      nfs.Write(buffed, 0,len); 
      //Increase the bytes Read counter 
      rdby=rdby+len ;  
     } 
     fin.Close(); 
    } 
} 
+0

あなたは1つのCommitRequestを受け取るか、複​​数のCommitRequestsを受け取るが、ダウンロードするのは1つのファイルしか受け取らないことがありますか? – SpeksETC

+0

CommitRequestの目的は、クライアントがファイルをサーバーから受信する準備をするためにファイル名とファイルサイズを送信し、クライアントがダウンロードメソッドを呼び出させることです。私はそれを確認する方法を知らない。デバッグは私のために働いていません。私の問題は、たとえば、サーバーはabc.txtとdef.txtの2つのファイルを送信しますが、クライアントはabc.txtのみを受信し、このファイルのサイズはサーバー上のabc.txt(1kb)よりも大きくなります。 – PeteMerry

答えて

0

問題は、ファイルバイトまたはトークンバイトとして受信バイトの治療に関連しています。クライアントコードがバッファーサイズと等しいバイトを読み取ろうとしています。サーバーは "CommitRequest"トークンとファイルバイトを次々に送信します。最初のファイルサイズが1200バイトであるとしましょう。サーバーはこれらの1200バイトを送信し、続いて2番目のファイルの後に2番目のファイルバイトが続く "CommitRequest"が続きます。今、クライアントは1024バイトの最初のファイルを読み込みます。そして、それは次の1024バイトを読み取るでしょう - しかし、これらのバイトは最初のファイルの残りの176バイト、サーバーからの "CommitRequest"応答、そして2番目のファイルの最初の数バイトを含みます。あなたのクライアントコードは、最初の176バイトしか取らず、次のファイルのデータを持つ次のバイトを無視します。

問題を解決するには、残りのバイトが処理されるようにするか(残っているバイトが部分的に "CommitRequest"応答を持つ可能性があるため、扱いにくい)、ソリューションを再構成して各ファイル転送クライアント要求後にのみ開始されます。

+0

回答ありがとうVinayC。私は何を意味していると思う。問題は同じファイルセットでも発生することに言及していませんでした。たとえば、サーバーはfile1、file2、file3の3つのファイルを送信します。クライアントが3つのファイルをすべて取得することもありますが、クライアントがfile1しか取得しないこともあります。 – PeteMerry

+0

これを変更した場合、これはうまくいくと思いますか?クライアントはダウンロードをクリックし、サーバーはすべてのファイル名とファイルサイズの文字列を送信します。クライアントがファイル名を文字列でforeachし、filenameでリクエストトークンを送信し、メソッドのダウンロードを呼び出す(上記のdownloadMapFromServer).Serverはトークン要求とファイル名を受け取り、そのファイル名でファイルを検索し、クライアント(ClientDownloadFromServer)にファイルを送信します。私は文字列からファイル名とサイズを取得する必要があります。あなたはこのことについてどう思いますか?エラーを修正しますか?それは効果的ですか? Thx 4 urは再び助けます。 – PeteMerry

+0

@PeteMerry、IMO、各ファイルを1つずつ要求するアプローチはうまく聞こえ、簡単です。ファイル名とサイズは、ファイル名に見つからないようなトークンシーケンス(||など)で区切ることができます(単純なstring.Splitはファイルのリストを取得します)。 – VinayC

関連する問題