2011-09-11 39 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部分,看看发生了什么 –