0

クライアントとサーバー間の単純なファイル転送アプリを開発しています。ここに私のコードがあります:私のクライアント(送信者):

try{
                File file_sender=XMLParser.register(peername, address, port, listfile);
                int count;
                byte[] buffer = new byte[1024];
                int len=(int) file_sender.length();
                byte[] mybytearray = new byte[len];     
                DataOutputStream output=new DataOutputStream(Info.connection.getOutputStream());
                output.writeInt(len);
                System.out.println(len);
                BufferedInputStream bis=new BufferedInputStream(new FileInputStream(file_sender));
                bis.read(mybytearray, 0, len);
                output.write(mybytearray, 0, len);
                bis.close();
                output.close();
               // Info.connection.close();
            }catch(Exception ex){
                System.out.println(ex.toString());
            }

私のサーバー(レシーバー):

public class IOThread extends Thread {
private Socket connection;
private DataInputStream input;
public IOThread(Socket connection) throws IOException{
    this.connection=connection;
    input=new DataInputStream(connection.getInputStream());

}
@Override
public void run(){
    while(true){
        try{
            int filesize=12022386;
            int bytesRead;
            int currentTot = 0;
            byte[] bytearray = new byte [filesize];
            int len=input.readInt();
            FileOutputStream fos = new FileOutputStream("data.xml");
            BufferedOutputStream bos = new BufferedOutputStream(fos);
            bytesRead=input.read(bytearray, 0,bytearray.length);
            System.out.println(len);
            currentTot=bytesRead;
            do{
                bytesRead=input.read(bytearray, currentTot, (bytearray.length-currentTot));
                if(bytesRead>=0) currentTot+=bytesRead;
                System.out.println("pos: "+currentTot);
            } while(len!=currentTot);
            bos.write(bytearray, 0, currentTot);
            bos.close();
            //connection.close();
            System.out.println("Done");
        }catch(EOFException ex){
            System.out.println(ex.toString());
            break;
        }catch( Exception ex){}
    }
}

複数のファイルを転送したいので、ソケットを閉じたくありません。そのため、変数「len」を使用して、ファイルが完全に転送されたことを確認します。

ファイルの送信後に「出力」を閉じると、サーバーは EOFException をスローし、ファイルは正常に送信されます。

出力を閉じないと、サーバーは成功したファイルを受信できません。しかし、サーバーは EOFException をスローしません。

この問題を解決するのを手伝ってもらえますか? 更新:クライアントで変数「出力」を閉じない場合のコンソール画面の出力は次のとおりです。

246

順位: 496

ありがとう。 下手な英語でごめんなさい

4

4 に答える 4

2

問題は、ファイルのサイズを超えて読み取ることです。つまり、lenバイトを読み取る代わりに、より大きなバイトを読み取ることですbytearray.length

その結果、サンプル出力からわかるようにlen、および.len!=currentTotcurrentTot == 496len == 246

while ループで次の変更を行います。

do{
   bytesRead=input.read(bytearray, currentTot, (len - currentTot));
   if(bytesRead>=0) currentTot += bytesRead;
   System.out.println("pos: " + currentTot);
} while(len != currentTot);

同様のエラーが原因で無限ループに陥らないようにするために、条件としてのcurrentTot < len代わりに使用できlen != currentTotます。

また、すでに を使用しているため、 を使用しDataInputStreamてソケットの内容を読み取ることを検討してreadFullyください。これは、指定されたバイト数がソケットから読み取られるまでブロックされるため、本質的に while ループが不要になります。詳細はこちらをご覧ください

于 2013-10-28T13:02:59.323 に答える
2

2つのこと:

まず、受信コードでファイルの長さを無視しているように見えますか? あなたが持っている:

        int filesize=12022386;
        int bytesRead;
        int currentTot = 0;
        byte[] bytearray = new byte [filesize];
        int len=input.readInt();

の値に関係なく bytearray のサイズを 12022386 バイトに設定lenし、入力ストリームからそのバイト数を要求しています。

次に、出力ストリームを閉じると、まだ書き込まれていないキャッシュ/バッファリングされたデータが自動的にフラッシュされます (つまり、この場合はサーバーに送信されます)。

最初のファイルの送信が完了したら、出力ストリームを明示的にフラッシュして、サーバーへのすべてのデータの送信を強制的に完了させます。その後、その出力ストリームを他の用途に使用し続けることができます。

output.flush()転送が完了したら、送信コードで実行します。

于 2013-10-28T12:40:49.610 に答える