2

ユーザーが多数のファイルをダウンロードできる 1 つのプログラムを開発しています。まず、ファイルのリストをユーザーに送信しています。そのため、ユーザーはリストから一度に 1 つのファイルを選択し、そのファイルを保存するパスを指定します。次に、サーバーに、ファイルが存在するファイルのパスも提供します。

ファイルサイズの制限なしでストリームのような体験を提供したいので、私はこのアプローチに従っています。

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

1)これは、アプリケーションを起動するたびに開始されるサーバーです

public class FileServer extends Thread {

    private ServerSocket socket = null;

    public FileServer() {
        try {
            socket = new ServerSocket(Utils.tcp_port);
        } catch (IOException e) {
            // TODO Auto-generated catch block
            e.printStackTrace();
        }
    }

    @Override
    public void run() {

        try {

            System.out.println("request received");
            new FileThread(socket.accept()).start();

        } catch (IOException ex) {
            ex.printStackTrace();
        }
    }

}

2) このスレッドはクライアントごとに個別に実行され、要求されたファイルを一度に 8kb のデータでユーザーに送信します。

public class FileThread extends Thread {

    private Socket socket;
    private String filePath;



    public String getFilePath() {
        return filePath;
    }

    public void setFilePath(String filePath) {
        this.filePath = filePath;
    }

    public FileThread(Socket socket) {
        this.socket = socket;
        System.out.println("server thread" + this.socket.isConnected());
        //this.filePath = filePath;
    }

    @Override
    public void run() {
        // TODO Auto-generated method stub
        try

        {
            ObjectInputStream ois=new ObjectInputStream(socket.getInputStream());
            try {
                           //************NOTE
                filePath=(String) ois.readObject();             
            } catch (ClassNotFoundException e) {
                // TODO Auto-generated catch block
                e.printStackTrace();
            }

            File f = new File(this.filePath);

            byte[] buf = new byte[8192];

            InputStream is = new FileInputStream(f);
            BufferedInputStream bis = new BufferedInputStream(is);

            ObjectOutputStream oos = new ObjectOutputStream(
                    socket.getOutputStream());
            int c = 0;

            while ((c = bis.read(buf, 0, buf.length)) > 0) {
                oos.write(buf, 0, c);
                oos.flush();
                // buf=new byte[8192];
            }

            oos.close();
            //socket.shutdownOutput();
            // client.shutdownOutput();
            System.out.println("stop");
            // client.shutdownOutput();
            ois.close();
//          Thread.sleep(500);

            is.close();
            bis.close();
            socket.close();
        } catch (IOException ex) {
            ex.printStackTrace();
        }

    }

}

注: ここで filePath は、サーバー上に存在するファイルのパスを表します。サーバーに接続しているクライアントがこのパスを提供します。私はソケットを介してこれを管理しており、このパスを正常に受信しています。

3) FileReceiverThread は、サーバーからデータを受信し、このバッファ データからファイルを構築する役割を果たします。

public class FileReceiveThread extends Thread {

    private String fileStorePath;
    private String sourceFile;
    private Socket socket = null;

    public FileReceiveThread(String ip, int port, String fileStorePath,
            String sourceFile) {
        this.fileStorePath = fileStorePath;
        this.sourceFile = sourceFile;
        try {
            socket = new Socket(ip, port);
            System.out.println("receive file thread " + socket.isConnected());
        } catch (IOException ex) {
            ex.printStackTrace();
        }
    }

    @Override
    public void run() {
        try {
            ObjectOutputStream oos = new ObjectOutputStream(
                    socket.getOutputStream());
            oos.writeObject(sourceFile);
            oos.flush();
            // oos.close();
            File f = new File(fileStorePath);

            OutputStream os = new FileOutputStream(f);
            BufferedOutputStream bos = new BufferedOutputStream(os);

            byte[] buf = new byte[8192];
            int c = 0;

            //************ NOTE

            ObjectInputStream ois = new ObjectInputStream(
                    socket.getInputStream());

            while ((c = ois.read(buf, 0, buf.length)) > 0) {
                // ois.read(buf);
                bos.write(buf, 0, c);
                bos.flush();
                // buf = new byte[8192];
            }

            ois.close();
            oos.close();
            //
            os.close();
            bos.close();

             socket.close();
            //Thread.sleep(500);
        } catch (IOException ex) {
            ex.printStackTrace();
        }
    }

}

注:私が直面している問題は、ファイルが初めて要求されたときであり、プログラムの結果は私の期待と同じです。初めてどんなサイズのファイルでも送信できます。2 番目のファイルが要求されると (たとえば、ファイル a、b、c、d をユーザーに送信し、ユーザーがファイル a を正常に受信し、ファイル b を要求している場合)、プログラムはこの状況でデッドロックに直面します。ソケットの入力ストリームを待っています。ブレークポイントを置いてデバッグしようとしましたが、FileThread の run メソッドで 2 回目は実行されません。ここで間違いを見つけることができませんでした。基本的に私は LAN 上で動作する LAN Messenger を作成しています。UI フレームワークとして SWT を使用しています。

4

2 に答える 2

2

より基本的な問題。

最初のソケットのみを処理しています。

while(true) {
    new FileThread(socket.accept()).start();
}
于 2012-04-13T13:51:19.757 に答える
0

Peter Lawrey の提案に従って、ソース コードからすべての冗長なストリーム コードを削除しました。現在、変更されたソース コードは次のとおりであり、問​​題は残っています。

1) FileServer に変更はありません。そのままです。

2) ファイルスレッド

public class FileThread extends Thread {

    private Socket socket;
    private String filePath;

    public String getFilePath() {
        return filePath;
    }

    public void setFilePath(String filePath) {
        this.filePath = filePath;
    }

    public FileThread(Socket socket) {
        this.socket = socket;
        System.out.println("server thread" + this.socket.isConnected());
        // this.filePath = filePath;
    }

    @Override
    public void run() {
        // TODO Auto-generated method stub
        try

        {
            OutputStream oos = socket.getOutputStream();
            oos.flush();

            InputStream ois = socket.getInputStream();
            byte[] buf = new byte[8192];

            ois.read(buf);
            filePath = new String(buf);
            System.out.println(filePath);

            File f = new File(this.filePath);

            InputStream is = new FileInputStream(f);

            int c = 0;

            while ((c = is.read(buf, 0, buf.length)) > 0) {
                oos.write(buf, 0, c);
                oos.flush();
            }

            oos.close();
            System.out.println("stop");
            ois.close();

            is.close();
        } catch (IOException ex) {
            ex.printStackTrace();
        }

    }

}

3) ファイルレシーバースレッド

public class FileReceiveThread extends Thread {

    private String fileStorePath;
    private String sourceFile;
    private Socket socket = null;

    public FileReceiveThread(String ip, int port, String fileStorePath,
            String sourceFile) {
        this.fileStorePath = fileStorePath;
        this.sourceFile = sourceFile;
        try {
            socket = new Socket(ip, port);
            System.out.println("receive file thread " + socket.isConnected());
        } catch (IOException ex) {
            ex.printStackTrace();
        }
    }

    @Override
    public void run() {
        try {
            OutputStream oos = socket.getOutputStream();

            oos.write(sourceFile.getBytes());
            oos.flush();

            File f = new File(fileStorePath);

            OutputStream os = new FileOutputStream(f);

            byte[] buf = new byte[8192];
            int c = 0;

            // ************ NOTE

            InputStream ois = socket.getInputStream();

            while ((c = ois.read(buf, 0, buf.length)) > 0) {

                os.write(buf, 0, c);
                os.flush();

            }

            ois.close();
            oos.close();

            os.close();

        } catch (IOException ex) {
            ex.printStackTrace();
        }
    }

}

私が見逃しているものはまだありますか?

于 2012-04-13T14:24:41.477 に答える