2012-04-13 16 views
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的第二次运行方法。我在这里找不到这个错误。基本上我正在制作局域网上的LAN Messenger。我正在使用SWT作为UI框架。

+0

[socket.close()](http://docs.oracle.com/javase/6/docs/api/java/net/Socket.html#close()“API javadoc”)滑 – gnat 2012-04-13 13:15:38

+0

@gnat:我不明白你在说什么......你能详细说明一下吗? – ankurtr 2012-04-13 13:26:14

+1

BTW:在创建ObjectInputStream之前,您应该创建并刷新ObjectOutputStream,否则会导致死锁。 – 2012-04-13 13:40:28

回答

2

更基本的问题。

您只处理第一个套接字。

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

那么,这里为每个文件请求单独的线程将运行,所以我认为是将有单独的套接字为每个客户共享相同的服务器。你是否试图说,一旦服务器的输入/输出流已经被使用,它们将不可用于任何其他客户端?如果你知道这个问题,请给出任何教程的好链接。 – ankurtr 2012-04-13 13:55:49

+0

对不起,我错过了显而易见的代码更短。 ;) – 2012-04-13 14:50:30

+0

谢谢了....我正在做这样一个愚蠢的错误...: - (..... – ankurtr 2012-04-13 15:13:45

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

} 

是还有一些东西,我很想念?在FileReceiveThread.run中使用[