2012-04-13 37 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中使用[