java - socket程序中线程面临死锁

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

最佳答案

一个更基本的问题。

您只处理第一个套接字。

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

关于java - socket程序中线程面临死锁,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/10141536/

相关文章:

java - 如何测试 ConcurrentHashMap 是否真正线程安全?

java - netty - 如何将 ChannelBuffer 类型保存到文件中?

c++ - Qt 中低延迟音频合成的最佳多线程方法是什么?

linux - 如何告诉另一个线程一个线程在 recv() 调用中*现在*

c++ - 一台服务器多客户端 C/C++

java - 在SQL数据库(例如H2)中插入和获取java.time.LocalDate对象

java - 无法找到/解决 Artifact : Maven error

multithreading - 单词的关系::'Thread' 和 'Core'

wpf - Dispatcher 与后台线程有何不同?

android - 如何对android中的 "keep-alive"包使用react?