2011-09-11 41 views
-1

我寫了一個聊天客戶端,工作正常,直到我決定添加一些文件發送者的東西,應該從客戶端發送文件到服務器。在我爲文件發件人添加行後,它不再顯示消息。爪哇聊天套接字寫入麻煩

我覺得麻煩在這裏,run()中有兩個try語句。

public void run(){ 

    InputStream input = null; 

    try{ 
     input = socket.getInputStream(); 
     BufferedReader inReader = new BufferedReader(new InputStreamReader(socket.getInputStream())); 
     BufferedWriter outReader = new BufferedWriter(new OutputStreamWriter(socket.getOutputStream())); 

     //Citeste calea fisierului 
     String filename = inReader.readLine(); 
     if(filename.equals("")){ 
      //Trimit status READY la client 
      outReader.write("READY\n"); 
      outReader.flush(); 
     } 

     FileOutputStream wr = new FileOutputStream(new File("C://tmp/"+filename)); 
     byte[] buffer = new byte[socket.getReceiveBufferSize()]; 
     int bytesReceived = 0; 
     while((bytesReceived = input.read(buffer)) > 0){ 
      wr.write(buffer,0,bytesReceived); 
     } 

    } 

    catch(IOException e){ 
     Logger.getLogger(ConectareClient.class.getName()).log(Level.SEVERE,null,e); 
    } 

    try{ 
     //Inregistreaza firul curent in listaObiecte 
     listaObiecte.addElement(this); 

     System.out.println("\n Fir de executie nou"); 
     System.out.println(this.toString()); 
     System.out.println(listaObiecte.toString()); 

     //Bucla 
     while(true){ 
      //Se citeste mesajul din fluxul de intrare trimis de client 
      String mesaj = fluxIntrare.readUTF(); 
      //Se transmite mesajul catre toti clientii conectati 
      transmite(mesaj); 
     } 
    } 
    //Tratare exceptie conexiune 
    catch (IOException e){ 
     e.printStackTrace(); 
    } 
    finally{ 
     //Stergere fir curent din listaObiecte 
     listaObiecte.removeElement(this); 

     System.out.println("\n Fir de executie inchis"); 
     System.out.println(this.toString()); 
     System.out.println(listaObiecte.toString()); 

     try{ 
      //Inchidere socket 
      socket.close(); 
      input.close(); 
     } 
     //Tratare exceptie conexiune 
     catch (IOException e){ 
      e.printStackTrace(); 
     }  
    } 
} 

    private static void transmite(String mesaj){ 
    //Enumerare generata de lista firelor de executie 
    Enumeration enm = listaObiecte.elements(); 

    //Cat timp mai sunt elemente in enumerare 
    while(enm.hasMoreElements()){ 
     //Se initializeaza cu null referinta firului curent 
     ConectareClient firDestinatie = null; 

     //Se protejeaza vectorul firelor de acces simultan 
     synchronized(listaObiecte){ 
      //Se memoreaza referinta catre firul curent 
      firDestinatie = (ConectareClient) enm.nextElement(); 
     } 
    //Referinta valida 
     if(firDestinatie != null){ 
      try{ 
       //Se protejeaza fluxul de iesire de acces simultan 
       synchronized(firDestinatie.fluxIesire){ 
        //Scriere mesaj in flux de iesire 
        firDestinatie.fluxIesire.writeUTF(mesaj); 
       } 
       //Mesajul este transmis 
       firDestinatie.fluxIesire.flush(); 
      } 
      catch(IOException e){ 
       firDestinatie.stop(); 
      } 
     } 
    }  
} 

在這裏,您可以下載所有的源文件。 http://www.megaupload.com/?d=ULFDBP6M

謝謝。

+0

客戶端可能會發送一個名爲'.. \ windows \ system32 \ user32.dll'的文件嗎? –

+0

好吧,文件發送部分來自我寫的另一個應用程序,它運行得很好,發送所有類型的文件。 –

+0

是的,這正是我試圖告訴你的問題。當客戶端發送包含「..」的文件名時,服務器將覆蓋完全不相關的文件,而不應該這樣做。在創建文件之前,您必須檢查*錯誤的文件名*。 –

回答

0

看起來在ConnectareClient.java中存在一個小的邏輯錯誤。發送「READY」的條件,我認爲應該是NOT條件,否則它永遠不會將該答覆發送給客戶端並繼續進行文件寫入。我已經試過了,我可以看到文件正在從客戶端複製到服務器。

下面是代碼的變化,我在ConnectareClient.java


//Citeste calea fisierului 
String filename = inReader.readLine(); 

// this seems should be a NOT condition 
if(!filename.equals("")){ 
    //Trimit status READY la client 
    outReader.write("READY\n"); 
    outReader.flush(); 
} 
+0

仍然無效 –

+0

錯誤是什麼?我改變的唯一其他事情是在Mac中將c:/ temp指向我的臨時目錄。如果您希望我們幫助您,而不是說它不起作用,您需要更具體。 – momo

+1

檢查您的客戶端在修改後是否從服務器獲取READY消息。 – momo

1

做我已經下載並嘗試你的代碼。總之,你的問題是線程死鎖。你有兩個線程,一個在服務器端,另一個在客戶端,每個線程都等待另一個線程來做一些事情,這樣第一個線程也可以繼續。

在更多的細節,這裏是怎麼了:

  • 的ClientChat課上線260發送文件名到服務器,然後等待服務器發送的東西回來(用字符串「READY」) ,然後繼續發送實際文件

  • 另一方面,ConectareClient類在第38行停止等待客戶端發送某些內容,然後繼續(併發送「READY」狀態消息,然後依次發送客戶正在等待)。

我給你的建議是:

這看起來很像一門功課asignement,一些塵封的老教授給了你:)它看起來像的傢伙給這個給你不經過第一去軟件開發的基礎知識。我不會在這裏編輯,但這裏有幾個實用的指針可以幫助你:

  • 使用IDE等Eclipse。不要使用記事本在命令行中編寫代碼。在這種情況下,Eclipse會爲您提供很多便利,只需輕鬆調試您的代碼即可輕鬆處理這些微不足道的錯誤。下面是你應該做的:下載Eclipse,創建一個Java標準項目,複製所有.java文件並將它們粘貼到Eclipse項目的「src」文件夾中。然後在上面提到的幾行中添加一些斷點,啓動客戶端和服務器,嘗試發送文件並查看代碼中發生了什麼。

  • 進行單元測試!無論你的教授和你的高校可能會說什麼,這都是非常重要的。做單元測試對你的編碼有雙重好處:1.它可以幫助你輕鬆地發現這種重構迴歸錯誤。 2.它會迫使你編寫出乾淨的代碼,併爲每個任務提供單獨的方法等。

  • 儘管服務器/客戶端低級別的線程和套接字知識並不差,但實現您在此項目中嘗試執行的更好方法是使用Java Messenger Service。它是一個完全按照你想要的方式工作的框架,即以同步或異步方式發送和接收所有類型的東西(原語,對象等),並且所有的腳手架已經爲你完成了,你只需要實現業務邏輯。看它,它可能會幫助你很多。

+0

感謝您的建議,我會嘗試刪除等待READY部分,看看發生了什麼 –