2014-07-10 62 views
0

我已經編寫了一個程序,它使用多點傳送來發現本地網絡上的對等方並允許它們之間的文件傳輸。它的工作原理,除了一些獲取文件/初始化傳輸線程的過程非常緩慢。它掛起約10-15秒,然後開始傳輸,並正常完成:在執行SwingWorker之前掛起Java文件傳輸程序

Transfer.java

  • 我的JFrame GUI類。這是爲了方便Netbeans完成的,因此任何生成的代碼都不會在這裏發佈。

    package transfer; 
    
    import java.beans.PropertyChangeEvent; 
    import java.io.File; 
    import java.io.IOException; 
    import java.util.logging.Level; 
    import java.util.logging.Logger; 
    import javax.swing.JFileChooser; 
    import static javax.swing.JFileChooser.FILES_AND_DIRECTORIES; 
    import javax.swing.SwingWorker; 
    import javax.swing.UIManager; 
    import javax.swing.UnsupportedLookAndFeelException; 
    
    public class Transfer extends javax.swing.JFrame { 
    
        private final FileDrop fileDrop; 
        private Client client; 
        private final Server server; 
        private final ClientMulticast clientMulticast; 
        private final ServerMulticast serverMulticast; 
    
        public Transfer() throws IOException { 
         initComponents(); 
    
         this.setTitle("Transfer"); 
         peerBox.setEditable(false); 
         peerBox.removeAllItems(); 
    
         fileDrop = new FileDrop(backgroundPanel, (java.io.File[] files) -> { 
    
          System.out.println(files[0].isDirectory()); 
    
          if (peerBox.getSelectedIndex() != -1) { 
    
           sendLabel.setText("Hello"); 
           try { 
            client = new Client(sendLabel, files, (Peer) peerBox.getSelectedItem()); 
    
            //Client property change listener - listens for updates to progress bar 
            client.addPropertyChangeListener((PropertyChangeEvent evt1) -> { 
    
             if (null != evt1.getPropertyName()) switch (evt1.getPropertyName()) { 
              case "progress": 
               sendProgressBar.setValue((Integer) evt1.getNewValue()); 
               break; 
             } 
            }); 
    
            client.execute(); 
    
           } catch (Exception ex) { 
            System.out.println("Unable to send! IOException in FileDrop call."); 
            ex.printStackTrace(System.out); 
           } 
    
          } else { 
           sendLabel.setText("Host not found"); 
          } 
         }); 
    
    
         sendProgressBar.setMaximum(100); 
         sendProgressBar.setMinimum(0); 
         receiveProgressBar.setMaximum(100); 
         receiveProgressBar.setMinimum(0); 
    
    
         server = new Server(receiveLabel); 
    
         //Server property change listener - listens for updates to progress bar 
         server.addPropertyChangeListener((PropertyChangeEvent evt1) -> { 
          if ("progress".equals(evt1.getPropertyName())) { 
           receiveProgressBar.setValue((Integer) evt1.getNewValue()); 
          } 
         }); 
    
         server.execute(); 
    
         serverMulticast = new ServerMulticast(); 
         serverMulticast.execute(); 
         clientMulticast = new ClientMulticast(peerBox); 
         clientMulticast.execute(); 
    
        } 
    
        ...GENERATED CODE... 
    
        private void openButtonActionPerformed(java.awt.event.ActionEvent evt) {           
         Transfer guiObject = this; 
    
         SwingWorker openFile = new SwingWorker<Void, String>() { 
    
          @Override 
          protected Void doInBackground() throws Exception { 
    
           openButton.setEnabled(false); 
    
           fileChooser.setFileSelectionMode(FILES_AND_DIRECTORIES); 
    
           int returnVal = fileChooser.showOpenDialog(guiObject); 
    
           if (returnVal == JFileChooser.APPROVE_OPTION && peerBox.getSelectedIndex() != -1) { 
    
           File[] fileArray = fileChooser.getSelectedFiles();      
    
           client = new Client(sendLabel, fileArray, (Peer) peerBox.getSelectedItem()); 
    
           //Client property change listener - listens for updates to progress bar 
           client.addPropertyChangeListener((PropertyChangeEvent evt1) -> { 
            if ("progress".equals(evt1.getPropertyName())) { 
             sendProgressBar.setValue((Integer) evt1.getNewValue()); 
            } 
           }); 
    
           client.execute(); 
    
           //block this swingworker until client worker is done sending 
           while(!client.isDone()) { } 
          } 
    
           openButton.setEnabled(true); 
    
           return null; 
          } 
         }; 
    
          openFile.execute(); 
        }           
    
    
        /** 
        * @param args the command line arguments 
        * @throws java.lang.ClassNotFoundException 
        * @throws java.lang.InstantiationException 
        * @throws java.lang.IllegalAccessException 
        * @throws javax.swing.UnsupportedLookAndFeelException 
        */ 
        public static void main(String args[]) throws ClassNotFoundException, InstantiationException, IllegalAccessException, UnsupportedLookAndFeelException { 
        System.setProperty("apple.laf.useScreenMenuBar", "true"); 
        System.setProperty("com.apple.mrj.application.apple.menu.about.name", "Transfer"); 
    
        UIManager.setLookAndFeel(javax.swing.UIManager.getSystemLookAndFeelClassName()); 
    
         /* Create and display the form */ 
         java.awt.EventQueue.invokeLater(() -> { 
          try { 
           new Transfer().setVisible(true); 
          } catch (IOException ex) { 
          Logger.getLogger(Transfer.class.getName()).log(Level.SEVERE, null, ex); 
         } 
        }); 
    } 
    
        // Variables declaration - do not modify      
        private javax.swing.JPanel backgroundPanel; 
        private javax.swing.JFileChooser fileChooser; 
        private javax.swing.JButton openButton; 
        private javax.swing.JComboBox<Peer> peerBox; 
        private javax.swing.JLabel receiveHeaderLabel; 
        private javax.swing.JLabel receiveLabel; 
        private javax.swing.JPanel receivePanel; 
        private javax.swing.JProgressBar receiveProgressBar; 
        private javax.swing.JLabel sendHeaderLabel; 
        private javax.swing.JLabel sendLabel; 
        private javax.swing.JPanel sendPanel; 
        private javax.swing.JProgressBar sendProgressBar; 
        // End of variables declaration     
    } 
    

ClientMutlicast.java

  • 發送多播數據包和接收響應 - 相應地修改GUI。這門課是錯誤的地方。

    package transfer; 
    
    import java.io.IOException; 
    import java.lang.reflect.InvocationTargetException; 
    import java.net.DatagramPacket; 
    import java.net.DatagramSocket; 
    import java.net.InetAddress; 
    import java.net.SocketException; 
    import java.net.SocketTimeoutException; 
    import java.util.ArrayList; 
    import java.util.List; 
    import java.util.concurrent.TimeUnit; 
    import javax.swing.JComboBox; 
    import javax.swing.SwingUtilities; 
    import javax.swing.SwingWorker; 
    
    public class ClientMulticast extends SwingWorker<Void, Peer> { 
    
    private boolean peerPreviouslyFound; 
    private byte[] sendData, receiveData; 
    private final DatagramSocket mSocket; 
    private DatagramPacket receivePacket; 
    private final JComboBox<Peer> peerBox; 
    private Peer peer; 
    private ArrayList<Peer> peerList; 
    
        public ClientMulticast(JComboBox<Peer> peerBox) throws SocketException { 
    
         peerList = new ArrayList<>(); 
         this.peerBox = peerBox; 
    
         mSocket = new DatagramSocket(); 
         mSocket.setBroadcast(true); 
         mSocket.setSoTimeout(300); 
    
         sendData = "CLIENT_MSG".getBytes(); 
        } 
    
         @Override 
         protected Void doInBackground() throws IOException, InterruptedException, InvocationTargetException { 
          while (true) { 
           try { 
            receiveData = new byte[1024]; 
            receivePacket = new DatagramPacket(receiveData, receiveData.length); 
    
            peerPreviouslyFound = false; 
    
            //send broadcast message 
            mSocket.send(new DatagramPacket(sendData, sendData.length, InetAddress.getByName("239.255.255.255"), 8888)); 
    
            //receive response 
            mSocket.receive(receivePacket); 
    
            //don't have to worry about responses from local host because 
            //server rejects multicast packets from local host 
            peer = new Peer(receivePacket.getAddress(), receivePacket.getPort(),       System.currentTimeMillis()); 
    
           for (Peer peerList1 : peerList) { 
            if (peerList1.getIPAddress().equals(peer.getIPAddress())) { 
             peerList1.setTimestamp(System.currentTimeMillis()); 
             peerPreviouslyFound = true; 
             break; 
            } 
           } 
    
           //add to peer list only if reponse is valid, not from local host, and not previously received from this host 
           if ("SERVER_RESPONSE".equalsIgnoreCase(new String(receivePacket.getData()).trim()) 
           && !peerPreviouslyFound) { 
    
            //publish(peer); 
            peerBox.addItem(peer); 
            peerList.add(peer); 
           } 
    
           for (int i = 0; i < peerList.size(); i++) { 
            //if peer is greater than 5 seconds old, remove from list 
            if (peerList.get(i).getTimestamp() + 5000 < System.currentTimeMillis()) { 
             peerBox.removeItemAt(i); 
             peerList.remove(i); 
            } 
           } 
          } catch (SocketTimeoutException ex) { 
           for (int i = 0; i < peerList.size(); i++) { 
            //if peer is greater than 5 seconds old, remove from list 
            if (peerList.get(i).getTimestamp() + 5000 < System.currentTimeMillis()) { 
             final int j = i; 
    
             SwingUtilities.invokeAndWait(() -> { 
              peerBox.removeItemAt(j); 
              peerList.remove(j); 
             }); 
    
            } 
           } 
          } 
    
          TimeUnit.MILLISECONDS.sleep(500); 
         }//end while 
        } 
    
        @Override 
        protected void process(List<Peer> p) { 
         peerBox.addItem(p.get(p.size() - 1)); 
         peerList.add(p.get(p.size() - 1)); 
        } 
    
    } 
    

我敢肯定,當UI構造內的FileDrop對象嘗試使用client.execute(執行客戶的SwingWorker)的問題是,有一個大的延遲。我可以調試它,但它不顯示任何問題。另外,我知道這個問題不能在Client()中調用socket.connect(),因爲在socket.connect()之前的print語句不會打印,直到程序從掛起的任何地方恢復。有任何想法嗎?我完全失去了。

- 編輯:上面的所有代碼都按需要工作,此處提到的錯誤已得到解決。如果有人想要完整的源代碼,我會很樂意分享它。

+0

在SwingWorker中使用'ProcessBuilder'的相關示例顯示爲[此處](http://stackoverflow.com/a/20603012/230513)。 – trashgod

+0

你能詳細說一下嗎?這個例子正在做同樣的事情,只是以不同的方式。我的SwingWorkers使用屬性更改偵聽器來更新進度條和process()方法,以安排EDT上的gui更新。他們正在使用後臺任務(從我能理解的方面)。你是說我錯誤地更新了GUI? – Timmah339

+0

這個詞_hangs_總是讓我懷疑阻止了EDT;但是,乍一看,我的工作人員看不到違規行爲;我的意思是建議一個完整的工作示例供參考。 – trashgod

回答

0

我將我的組合框傳遞給我的ClientMuticast類,名爲peerBox。我直接修改了這個結構,存儲了其中的對等體。這是阻塞接口線程,因爲ClientMulticast類不斷訪問/更改組合框。
我改變了代碼,使用組合框來只顯示gui的值並存儲發現的對等點。在每次調用ClientMulticast構造函數時,使用數組列表複製組合框中的所有值。如果發現對等方,則通過ClientMulticast類中的publish()process()方法更新組合框。任何放置在process()內的代碼將被安排在EDT上執行。