2012-04-13 4 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 пользователю, и пользователь успешно получил файл, и теперь он запрашивает файл b) в этой ситуации программа сталкивается с тупиковой ситуацией. Он ожидает входной поток сокета. Я поставил точку останова и попытался ее отладить, но второй раз не запускается метод FileThread. Я не мог узнать здесь ошибку. В основном я создаю LAN Messenger, который работает в локальной сети. Я использую SWT в качестве интерфейса пользовательского интерфейса.

+0

[socket.close()] (http://docs.oracle.com/javase/6/docs/api/java/net/Socket.html#close() «API javadoc») в FileReceiveThread.run чувствует slippery – gnat

+0

@gnat: Я не понимаю, что вы говорите ... Не могли бы вы подробнее рассказать? – ankurtr

+1

BTW: вы должны создать и очистить ObjectOutputStream до создания объекта ObjectInputStream, или это может привести к блокировке. –

ответ

2

Более общая проблема.

Вы обрабатываете только первый разъем.

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

Ну, вот для каждого запрошенного файла отдельный поток будет работать, так что я думал, что будет отдельный сокет для каждого клиента, который будет использовать один и тот же сервер. Вы пытаетесь сказать, что как только поток ввода/вывода сервера будет использован, они не будут доступны ни для какого другого клиента? Если вы знаете об этой проблеме, сообщите любую полезную ссылку на учебник. – ankurtr

+0

Простите, я пропустил очевидное, теперь код короче. ;) –

+0

Спасибо тонну .... я делал такую ​​глупую ошибку ...: - (..... – ankurtr

0

Согласно предложению Питера Лоури, я удалил весь код избыточных потоков из моего исходного кода. Теперь изменившийся исходный код выглядит следующим образом, и проблема остается.

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

} 

есть еще то, что я не хватает?

Смежные вопросы