1

2 つのプログラムを実装しています。クライアントとサーバー。クライアントはサーバーからローカル ファイル システムにダウンロードするファイルを要求します。

1 つのファイルをダウンロードした後、クライアントは必要に応じて別のファイルをダウンロードできる必要があります。

ただし、ファイルをダウンロードした後、サーバーから例外が表示されます

java.net.SocketException: Socket closed

これが私のコードです..

クライアント:

        byte[] aByte = new byte[0];
        int bytesRead;
        String msg;
        FileOutputStream fos = null;
        BufferedOutputStream bos = null;
        while (!(msg = input.readLine()).equals("end")) {

            String myFolderName = "ServerFolder";
            File folder=new File(myFolderName);   
            if (!folder.exists()){ 
                folder.mkdir();
            }
            System.out.println("file downloading");
            try {

                System.out.println("1");
                fos = new FileOutputStream("ServerFolder/"+fileToDownload);
                bos = new BufferedOutputStream(fos);

                System.out.println("MSG: "+msg);

                bytesRead = in.read(aByte, 0, aByte.length);

                System.out.println("2");



                do {
                    baos.write(aByte);
                    bytesRead = in.read(aByte);
                } while (bytesRead != -1);

                System.out.println("3");
                bos.write(baos.toByteArray());
                bos.flush();
            } catch (IOException ex) {
                System.err.println(ex.getMessage());
            }


        }
        bos.close();

    } catch (IOException ex) {
        System.err.println(ex);
    }    

サーバ:

if (outToClient != null) {
                    System.out.println("2");
                    File myFile = new File(msg);
                    byte[] mybytearray = new byte[(int) myFile.length()];


                    try {
                        fis = new FileInputStream(myFile);
                    } catch (FileNotFoundException ex) {
                        // Do exception handling
                    }
                    System.out.println("3");
                    bis = new BufferedInputStream(fis);

                    try {
                        bis.read(mybytearray, 0, mybytearray.length);   

                        System.out.println("mybytearray.length: "+(int) myFile.length());
                        out.write((int) myFile.length()+"\r\n");    
                        out.write("end\r\n");
                        out.flush();


                        outToClient.write(mybytearray, 0, mybytearray.length);
                        outToClient.flush();

                        s.shutdownOutput();

                        outToClient.close();


                        System.out.println("4");

                    } catch (IOException ex) {
                        System.out.println("5");
                        System.err.println(ex);
                    }

(すべての接続は各メソッドの最初で行われます)

私が持っていた

s.close();

サーバー内ですが、エラーが発生した場合に備えて削除しましたが、そうではありません..

私はそれを推測しています

outToClient.close();

も原因ではないでしょうか? ...

また、私はこの問題をグーグルで検索し、サーバーがファイルを送信する前にクライアントにファイルのサイズを伝えることを提案した人もいました..しかし、それもうまくいきませんでした..その部分も削除しました(または間違っていたのかもしれません) ..)

ありがとう:)

4

1 に答える 1

3

java.net.SocketException: ソケットが閉じられました

この意味はただ一つ。ソケットを閉じてから、それを使い続けました。Socket の入力ストリームまたは出力ストリームのいずれかを閉じると、他のストリームとソケットが閉じられることに気付いていない可能性があります。

コードには他にも多くのエラーがあります。read() によって返される値を無視しています。ターゲットに直接書き込む可能性があるときに、不要な BytearrayOutputStreams を使用しています。などなど。本当に言及するには多すぎます。Java でストリームをコピーする正規の方法は次のとおりです。

while ((count = in.read(buffer)) > 0)
{
  out.write(buffer, 0, count);
}

同じ接続を使用して複数のファイルを転送する場合は、ファイルの前にファイルの長さを送信する必要があります。これにより、ピアは、上記のループの明らかな変更を使用して、すべてのファイルをいつ読み取ったかを知ることができます。DataOutputStream.writeLong()そして、それをDataInputStream.readLong()行うための最も明白な方法を提供します。

于 2012-10-03T10:38:57.733 に答える