2

我正在开发一个程序,用户可以在其中下载许多文件。现在首先我将文件列表发送给用户。因此,用户一次从列表中选择一个文件并提供存储该文件的路径。反过来,它还为服务器提供文件所在的路径。

我之所以采用这种方法,是因为我想在没有文件大小限制的情况下提供类似流的体验。

这是我的代码..

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();
        }
    }

}

注意:现在我面临的问题是第一次请求文件时,程序的结果与我的预期相同。我能够在第一时间传输任何大小的文件。现在,当请求第二个文件时(例如,我已将文件 a、b、c、d 发送给用户并且用户已成功接收文件 a,现在他正在请求文件 b)程序在这种情况下面临死锁。它正在等待套接字的输入流。我放了断点并试图调试它,但它第二次没有进入 FileThread 的运行方法。我在这里找不到错误。基本上我正在制作一个在局域网上工作的局域网信使。我使用 SWT 作为 UI 框架。

4

2 回答 2

2

一个更基本的问题。

您只处理第一个套接字。

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

根据 Peter Lawrey 的建议,我从源代码中删除了所有冗余流代码。现在修改后的源代码如下,问题依旧。

1) 文件服务器没有变化。它就是这样。

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) 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 {
            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 回答