2014-05-04 71 views
1

我正在嘗試創建服務器和客戶端應用程序,其中服務器可以向客戶端發送消息,並且客戶端只能接受來自服務器的消息。Java .jar文件無法接收套接字消息

我已經成功實現了這個目標。問題是,client.jar不會從服務器收到任何消息。但是,在netbean中一切正常。

任何想法爲什麼會發生這種情況?

這裏是我完整的服務器代碼:

public sServerUI() { 
    super("Server : "+System.getenv("COMPUTERNAME")); // mendapatkan nama komputer 
    initComponents(); 
} 

public void startListener(){  
    Random randomGen = new Random(); 
    try{ 
     myPort = randomGen.nextInt(9999); 
     server = new ServerSocket(myPort);//Bebas portnya, tp nggk boleh sudah terpakai atau pakai random jg bisa 
     btnListen.setEnabled(false); 
     while(key == null) { 
      key = JOptionPane.showInputDialog(this, "Input your Key : ", "Insert Key", JOptionPane.PLAIN_MESSAGE); 
     } 
     if(key.equals("")) { 
      key = "Random"; 
      txtMessage.setText(txtMessage.getText()+"Invalid key inputted, key automatically set to '"+key+"'\n"); 
     } else txtMessage.setText(txtMessage.getText()+"Key set to '"+key+"'\n"); 
    } catch (IOException e) {//Kalau sudah terpakai muncul error 
     JOptionPane.showMessageDialog(this, "Could not listen at " + myPort); 
     //Gagal, keluarin info 
    } finally{ 
     myPort = server.getLocalPort(); 
     lblPort.setText("Port: "+myPort); 
     System.out.println("Port: "+myPort); 
    } 

    acceptClient.start(); 
} 
public void windowClosing(WindowEvent e){ 
    try { 
     server.close(); 
     for (int i=0;i<numberOfClient;i++){ 
      socketIn[i].close(); 
      socketOut[i].close(); 
     } 
    } catch (IOException ex) { 
     System.out.println("Error "+ex.getMessage()); 
    } 
} 

class Accepter extends Thread{ 
    @Override 
    public void run(){ 
     while (true){ 
      try{ 
       client[numberOfClient] = server.accept(); 
       numberOfClient++; 
       lblStatus.setText("Status: "+numberOfClient+" client(s) connected"); 

       Handler handleClient = new Handler(numberOfClient-1); 
       handleClient.start(); 
      } catch (IOException e) { 
       JOptionPane.showMessageDialog(null, "Accept failed: " + myPort); 
      } 
     } 
    } 
} 
class Handler extends Thread{ 
    private int arr; 
    Handler(int ar){ 
     arr = ar; 
     try{ 
      socketIn[arr] = new BufferedReader(new InputStreamReader(client[arr].getInputStream())); 
      socketOut[arr] = new PrintWriter(client[arr].getOutputStream(), true); 
     } catch (IOException e) { 
      JOptionPane.showMessageDialog(null, "Read failed"); 
     } 
    } 

    @Override 
    public void run(){ 
     while (true){ 
      try{ 
       if (socketIn[arr].ready()){ 
        System.out.println("Reading..."); 
        line = socketIn[arr].readLine(); 
        if (!txtMessage.getText().equals("")){ 
         txtMessage.setText(txtMessage.getText()+"\n"); 
         //broadcast message ke client2 lain 
        } 
        txtMessage.setText(txtMessage.getText()+"Client "+(arr+1)+": "+line); 

        for (int i=0;i<numberOfClient;i++){ 
         if (i!=arr){//jgn kembaliin ke client yg kirim 
          socketOut[i].println("Client "+(arr+1)+": "+line); 
         } 
        } 
       } 
      } catch (IOException e) { 
       System.out.println("Read failed"); 
      } 
     } 
    } 
} 
private void btnListenActionPerformed(java.awt.event.ActionEvent evt) {           
    // TODO add your handling code here: 
    startListener(); 
} 
private void sendData(String data) { 
    for (int j=0;j<numberOfClient;j++){ 
     socketOut[j].println(data); 
    } 
} 

private void btnSendActionPerformed(java.awt.event.ActionEvent evt) {           
    // TODO add your handling code here: 
    if(numberOfClient > 0) { 
     int packetIndex = 1; 
     String ext = getExt(filePath, '.'); 
     String sData = "start"+pemisahString+fByte.length+pemisahString+ext+pemisahString; //menaruh kata kunci 'start' dan ukuran file di awal message, serta extensionnya 
     sendData(sData); 
     sData = ""; 
     int k = 0; 
     for(int i = 0; i < fByte.length; i++) { 
      if(k >= Math.ceil((double)fByte.length/10.0)) { 
       k = 0; 
       sData = rc4(key, sData); 
       sendData(Integer.toString(packetIndex)+pemisahString+sData); 
       txtMessage.setText(txtMessage.getText()+"packet-"+packetIndex+" sent ! isi : "+revertToString(rc4(key,revertToString(sData)))+"\n"); 
       packetIndex++; 
       sData = ""; 
      } 
      sData += fByte[i]; 
      sData += pemisahString; 
      k++; 
      if(i == fByte.length-1) { 
       sData = rc4(key, sData); 
       sendData(Integer.toString(packetIndex)+pemisahString+sData); 
       txtMessage.setText(txtMessage.getText()+"packet-"+packetIndex+" sent ! isi : "+revertToString(rc4(key,revertToString(sData)))+"\n"); 
       packetIndex++; 
       sData = ""; 
      } 
     } 
     sData = "end"+pemisahString; 
     sendData(sData); 
     txtMessage.setText(txtMessage.getText() + "Done ! divided into "+k+" piece(s) per packet\n"); 
    } else JOptionPane.showMessageDialog(this, "No Client Connected !", "Error", JOptionPane.ERROR_MESSAGE); 
}          

private void fileBtnActionPerformed(java.awt.event.ActionEvent evt) {           
    // TODO add your handling code here: 
    JFileChooser chooser = new JFileChooser(); 
    chooser.setCurrentDirectory(new File("d:/Kul/Smstr 6/Kripto n Steno/Stream Cipher/")); 
    int returnVal = chooser.showOpenDialog(this); 

    if(returnVal == JFileChooser.APPROVE_OPTION) { 
     filePath = chooser.getSelectedFile().getPath(); 
     try { 
      inputFile = new File(filePath); 
      fIn = new FileInputStream(inputFile); 
      fByte = new byte[(int)inputFile.length()]; 
      System.out.println("file size : "+(int)inputFile.length()+" byte(s)"); 
      System.out.print("Isi file : "); 
      fIn.read(fByte); 
      fIn.close(); 
      for(int i = 0; i < fByte.length; i ++) { 
       System.out.print(fByte[i]+" "); 
      } 
      System.out.print("end of file\n"); 

      String stringBuatDitampilin = getExt(filePath, (char)92); 

      txtMessage.setText(txtMessage.getText() + "'" + stringBuatDitampilin + "' Loaded !\n"); 
      btnSend.setEnabled(true); 
      //fIn.close(); 
      //JOptionPane.showMessageDialog(this, "File Loaded !", "Success", JOptionPane.INFORMATION_MESSAGE); 
     } catch(java.io.IOException e) { 
      JOptionPane.showMessageDialog(this, e.toString(), "IO Error", JOptionPane.ERROR_MESSAGE); 
     } 
    } 
}   
public static void main(String args[]) { 
    /* Set the Nimbus look and feel */ 
    //<editor-fold defaultstate="collapsed" desc=" Look and feel setting code (optional) "> 
    /* If Nimbus (introduced in Java SE 6) is not available, stay with the default look and feel. 
    * For details see http://download.oracle.com/javase/tutorial/uiswing/lookandfeel/plaf.html 
    */ 
    try { 
     for (javax.swing.UIManager.LookAndFeelInfo info : javax.swing.UIManager.getInstalledLookAndFeels()) { 
      if ("Nimbus".equals(info.getName())) { 
       javax.swing.UIManager.setLookAndFeel(info.getClassName()); 
       break; 
      } 
     } 
    } catch (ClassNotFoundException | InstantiationException | IllegalAccessException | javax.swing.UnsupportedLookAndFeelException ex) { 
     java.util.logging.Logger.getLogger(sServerUI.class.getName()).log(java.util.logging.Level.SEVERE, null, ex); 
    } 
    //</editor-fold> 

    /* Create and display the form */ 
    java.awt.EventQueue.invokeLater(new Runnable() { 
     @Override 
     public void run() { 
      new sServerUI().setVisible(true); 
     } 
    }); 
} 

,這裏是我的完整的客戶端代碼:

public sClientUI() { 
    super("Client"); 
    initComponents(); 
} 

public void listenSocket(){ 
//Create socket connection 
    try{ 
     socket = new Socket(txtHost.getText(), Integer.parseInt(txtPort.getText())); 
     socketOut = new PrintWriter(socket.getOutputStream(), true); 
     socketIn = new BufferedReader(new InputStreamReader(socket.getInputStream())); 
     txtMessage.setText(txtMessage.getText()+"Succesfully connected to "+txtHost.getText()+" !\n"); 
     while(key == null) { 
      key = JOptionPane.showInputDialog(this, "Input your Key : ", "Insert Key", JOptionPane.PLAIN_MESSAGE); 
     } 
     if(key.equals("")) { 
      key = "Random"; 
      txtMessage.setText(txtMessage.getText()+"Invalid key inputted, key automatically set to '"+key+"'\n"); 
     } else txtMessage.setText(txtMessage.getText()+"Key set to '"+key+"'\n"); 
     txtHost.setEditable(false); 
     txtPort.setEditable(false); 
     btnConnect.setEnabled(false); 
     myListener = new Timer(250, readLine); 
     myListener.start(); 
    } catch (UnknownHostException e) { 
     JOptionPane.showMessageDialog(this, "Unknown host: "+e.getMessage(), "Unknown Hostname", JOptionPane.ERROR_MESSAGE); 
    } catch (IOException e) { 
     JOptionPane.showMessageDialog(this, "Either your hostname is wrong, or you entered wrong port number\n"+e.getMessage(),"Input Error", JOptionPane.ERROR_MESSAGE); 
    } catch (NumberFormatException e) { 
     JOptionPane.showMessageDialog(this, e.getMessage(),"Invalid Port Number", JOptionPane.ERROR_MESSAGE); 
    } 
} 

public void windowClosing(WindowEvent e){ 
    try { 
     socket.close(); 
     socketIn.close(); 
     socketOut.close(); 
    } catch (IOException ex) { 
     System.out.println("Error "+ex.getMessage()); 
    } 
} 
ActionListener readLine = new ActionListener(){ 
    @Override 
    public void actionPerformed(ActionEvent ae) { 
     try{ 
      if (socketIn.ready()){ 
       String tempReceiver; 
       if((tempReceiver = socketIn.readLine()) != null) { 
        exStr(tempReceiver); //untuk memotong-motong string dan meng-create file baru 
       } 
      } 
     } catch (IOException e) { 
      System.out.println("Read failed"); 
     } 
    } 
}; 
private void btnConnectActionPerformed(java.awt.event.ActionEvent evt) {           
    // TODO add your handling code here: 
    listenSocket(); 
} 
public static void main(String args[]) { 
    /* Set the Nimbus look and feel */ 
    //<editor-fold defaultstate="collapsed" desc=" Look and feel setting code (optional) "> 
    /* If Nimbus (introduced in Java SE 6) is not available, stay with the default look and feel. 
    * For details see http://download.oracle.com/javase/tutorial/uiswing/lookandfeel/plaf.html 
    */ 
    try { 
     for (javax.swing.UIManager.LookAndFeelInfo info : javax.swing.UIManager.getInstalledLookAndFeels()) { 
      if ("Nimbus".equals(info.getName())) { 
       javax.swing.UIManager.setLookAndFeel(info.getClassName()); 
       break; 
      } 
     } 
    } catch (ClassNotFoundException | InstantiationException | IllegalAccessException | javax.swing.UnsupportedLookAndFeelException ex) { 
     java.util.logging.Logger.getLogger(sClientUI.class.getName()).log(java.util.logging.Level.SEVERE, null, ex); 
    } 
    //</editor-fold> 

    /* Create and display the form */ 
    java.awt.EventQueue.invokeLater(new Runnable() { 
     @Override 
     public void run() { 
      new sClientUI().setVisible(true); 
     } 
    }); 
} 

將.jar客戶端和服務器連接到對方,他們就不能發或收到任何消息

+0

首先要檢查的是防火牆配置。也嘗試運行服務器和客戶端localhost地址 –

+0

@Tech 我已經設置了Windows防火牆(我使用的是Windows 7),允許我的應用程序使用入站和出站規則的網絡,但結果仍然相同。對不起,如果我的下一個問題有點愚蠢,但你的意思是什麼localhost地址?它是否像'127.0.0.1'? –

+0

jar文件是一個惰性對象。它不能「接收」任何東西。 –

回答

0

解決

那是因爲我使用一些加密算法加密 消息,我發送字節串 一些加密的字符是不可讀的控制檯,所以程序不能做某些按鍵操作處理消息

感謝所有無論如何:)

0

您的代碼缺少一些重要的和平。例如進口。他們向我們展示了您使用的圖書館,併爲我們提供了機會做一些研究。

1)例如行:

myListener = new Timer(250, readLine); 

它不能是java.util.Timer中,因爲這類不具有構造(長/ INT,的ActionListener)。可能這個調用只運行一次而不是多次,但我無法知道並告訴你。

2)又如:您有線

acceptClient.start(); 

我只能假設有可變

Accepter acceptClient = new Accepter(); 

一個實例,但它也可以是指一個完全不同的類工作方式不同

3)回到我的第一個例子:

你正在做某種輪詢。這在java中不是很好的風格,因爲Java Thready是專門針對阻塞線程而設計的。使用一個代碼塊這樣的,而不是(未經測試;由服務器代碼的啓發)

class ClientThread extends Thread{ 
    @Override 
    public void run(){ 
     try{ 
      String tempReceiver; 
      while ((tempReceiver = socketIn.readLine()) != null) { 
       exStr(tempReceiver); 
      } 
     } catch (IOException e) { 
      System.out.println("Read failed"); 
     } 
    } 
} 

在這種情況下,你不需要投票,你必須立即作出反應。這會消耗更少的CPU。 一個完全不同的選擇是使用Java NIO,它更適合單線程應用程序(或稱之爲少線程)。

一些題外話備註:

OT 1) 調用Swing的功能,如JOptionPane.showMessageDialog()setText()是線程危險。 Swing本身不是線程安全的。你應該在它周圍使用EventQueue.invokeLater()包裝。我最喜歡的:SwingUtils.invokeLater()

OT 2) 具有可變tempReceiver類全局(我想這是因爲我看不到任何聲明)也是危險的,因爲你有可能用它和別的地方可能正好在其覆蓋在另一個線程中調用readLine()exStr()(如果Timer是Swing實現,它將運行一個額外的線程)。

OT 3) 您在說「.jar客戶端和服務器已連接到對方」。這是否意味着您有兩個打開的控制檯窗口,並在每個窗口中運行java -jar命令?如果沒有,你可能會錯過一些重要的控制檯輸出(可能是例外)。 java的windows分佈有兩個java跑步者:javaw.exe當在瀏覽器中雙擊一個.jar文件時調用它。而且它也運行你的程序,同時打開一個控制檯窗口,顯示System.out.println的輸出等等。這個控制檯對於調試非常重要。它顯示與NetBeans或Eclipse中的「調試」窗口相同的輸出。

+0

我只問你打電話給你的程序。你在Windows資源管理器中雙擊jar嗎?然後你應該打開一個命令行窗口並輸入一個以'java'開始的命令,否則你會錯過你的代碼中任何地方發生的所有'System.out','System.err'和'printStackTrace'輸出。關於你的'readLine'改變:你仍在投票。這個想法是在不帶'socketIn.ready'的情況下調用'readLine()'。 readLine將阻塞該線程並等待直到有傳入數據。這可以立即響應您的應用程序。 - 請讓我們知道Timer類的包名稱 –

+0

感謝您的投票技巧!不過,我確實改變了一點,以適應我的需要。那麼我已經更新了我的帖子,它包含更完整的代碼。我很抱歉,但我不太瞭解控制檯窗口的事情。我應該使用命令提示符來運行java –

+0

是的,我會雙擊windows exploler中的jar。我使用'javax.swing.Timer'包。我明白了,我想明白我應該如何應用你的'readLine'技巧。那麼,回到主要問題,我的應用程序在netbeans中工作得很好,但是當我雙擊jar文件時它不起作用 –