线程在套接字程序中面临死锁

时间:2012-04-13 12:50:00

标签: java multithreading sockets

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

我正在遵循这种方法,因为我想在没有文件大小限制的情况下提供流体验。

这是我的代码..

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发送给用户并且用户已成功接收文件,现在他正在请求文件b),程序在这种情况下面临死锁。它正在等待套接字的输入流。我把断点并尝试调试它,但它不是第二次在FileThread的run方法中。我在这里找不到错误。基本上我正在制作一个在LAN上工作的LAN Messenger。我使用SWT作为UI框架。

2 个答案:

答案 0 :(得分:2)

更基本的问题。

您只处理第一个套接字。

while(true) {
    new FileThread(socket.accept()).start();
}

答案 1 :(得分:0)

根据Peter Lawrey的建议,我从源代码中删除了所有冗余流代码。现在更改的源代码如下,问题仍然存在。

1)FileServer没有变化。它就是这样。

2)FileThread

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

}

还有什么东西我不见了?