2015-06-08 91 views
0

我正在製作一個程序,它接收一個文件,並通過套接字將其發送到客戶端。客戶端收到它並將其保存到文件中。這就是它應該做的。Java套接字接收字節數組,其中每個字節是0

但不知何故,客戶端收到的字節數組只包含0個字節,所以我的輸出文件是空的。這裏是代碼:

服務器:

try { 
     serverSocket=new ServerSocket(7575); 
     serverSocket.setSoTimeout(1000000); 
     System.out.println("serverSocket created."); 
    } catch (IOException ex) { 
     Logger.getLogger(Server.class.getName()).log(Level.SEVERE, null, ex); 
     System.out.println("Error in creating new serverSocket on port 7575"); 
    } 

    for(int i=0;i<array.length;i++) 
     System.out.println(array[i]); 

    Socket socket=null; 
    try { 
     System.out.println("Waiting for client..."); 
     socket=serverSocket.accept(); 
     System.out.println("Client accepted."); 
    } catch (IOException ex) { 
     Logger.getLogger(Server.class.getName()).log(Level.SEVERE, null, ex); 
    } 
    PrintWriter outWriter=null; 
    DataOutputStream outputStream=null; 
    OutputStream os=null; 
    BufferedOutputStream bos=null; 
    try { 
     os=socket.getOutputStream(); 
     outputStream=new DataOutputStream(os); 
     outWriter=new PrintWriter(socket.getOutputStream()); 
     bos=new BufferedOutputStream(socket.getOutputStream()); 
     System.out.println("Server streams created."); 
    } catch (IOException ex) { 
     Logger.getLogger(Server.class.getName()).log(Level.SEVERE, null, ex); 
    } 
    System.out.println("sending name "+name); 
    outWriter.println(name); 
    outWriter.flush(); 

    outWriter.println(array.length); 
    outWriter.println("array.length"+array.length); 
    outWriter.flush(); 

    try { 
     os.write(array); 
     os.flush(); 
    } catch (IOException ex) { 
     Logger.getLogger(Server.class.getName()).log(Level.SEVERE, null, ex); 
     System.out.println("couldnt send array of bytes"); 
    } 



    try { 
     os.close(); 
     outputStream.close(); 

     socket.close(); 
    } catch (IOException ex) { 
     Logger.getLogger(Server.class.getName()).log(Level.SEVERE, null, ex); 
    } 

客戶端:

public class Client implements Runnable { 
private Socket socket; 
private String folderPath; 

public Client(String p) 
{ 
    folderPath=p; 
} 

@Override 
public void run() 
{ 
    try { 
     System.out.println("Client connecting to localhost on 7575 port..."); 
     socket=new Socket("localhost", 7575); 
    } catch (IOException ex) { 
     Logger.getLogger(Client.class.getName()).log(Level.SEVERE, null, ex); 
    } 

    BufferedReader reader=null; 
    BufferedInputStream bis=null; 
    InputStream input=null; 
    DataInputStream in=null; 
    try { 
     System.out.println("creating streams"); 
     reader=new BufferedReader(new InputStreamReader(socket.getInputStream())); 
     input=socket.getInputStream(); 
     in=new DataInputStream(input); 
     bis=new BufferedInputStream(socket.getInputStream()); 
     System.out.println("streams created!"); 
    } catch (IOException ex) { 
     Logger.getLogger(Client.class.getName()).log(Level.SEVERE, null, ex); 
    } 
    String name=""; 
    int size=0; 
    String s="32"; 
    try { 
     name=reader.readLine(); 
     s=reader.readLine(); 
    } catch (IOException ex) { 
     Logger.getLogger(Client.class.getName()).log(Level.SEVERE, null, ex); 
    } 
    if(s!=null) 
    size=Integer.parseInt(s); 
    System.out.println("name: "+name); 
    System.out.println("size: "+size); 

    byte [] arr=new byte[size]; 
    try { 
     input.read(arr); 
    } catch (IOException ex) { 
     Logger.getLogger(Client.class.getName()).log(Level.SEVERE, null, ex); 
     System.out.println("couldnt read the byte array"); 
    } 

    for(int i=0;i<arr.length;i++) 
     System.out.println(arr[i]); 

    FileOutputStream fos=null; 
    try { 
     fos=new FileOutputStream(folderPath+"/"+name); 
     } catch (FileNotFoundException ex) { 
      System.out.println("Could write the file"); 
     Logger.getLogger(Client.class.getName()).log(Level.SEVERE, null, ex); 
    } 
    try { 

     fos.write(arr); 
     fos.flush(); 
     } catch (IOException ex) { 
      System.out.println("Could write the file2"); 
     Logger.getLogger(Client.class.getName()).log(Level.SEVERE, null, ex); 
    } 

    try { 
     fos.close(); 
     } catch (IOException ex) { 
     Logger.getLogger(Client.class.getName()).log(Level.SEVERE, null, ex); 
    } 


     try { 
     in.close(); 
     input.close(); 
     reader.close(); 
     socket.close(); 
     } catch (IOException ex) { 
     Logger.getLogger(Client.class.getName()).log(Level.SEVERE, null, ex); 
     } 



} 

}

+0

不要在同一套接字上使用多個閱讀器,編寫器和流。它不會工作。選擇一種技術並堅持下去。 – EJP

回答

2

在同一個數據流上混合使用二進制和文本模式很棘手。你會被建議不要這樣做。使用DataInputStream(用於名稱,計數和文件內容)是一種可能的解決方案。 (這就是我會嘗試的)。另一種方法是將文件內容編碼爲文本(例如使用Base64編碼)。

您當前的「混合流:代碼在客戶端」的問題。當您從BufferedReader讀取名稱和大小時,將導致讀取器從套接字讀取並緩衝最多4096個字節。是一些字節是文件內容所以,當你再嘗試讀取從底層InputStream這裏的內容:。

input.read(arr); 

,你可能會發現,有沒有什麼可以讀取結果:一個空的或損壞的文件。


The也是另一個問題。您的代碼假定input.read(arr)語句將讀取流的其餘部分,或者直到它填充字節數組。這個假設是不正確的。當您從套接字流中讀取數據時,read只會返回當前可用的字節(位於客戶端網絡堆棧中)。

再次,結果可能是一個損壞的文件。 (在這種情況下截斷。)

讀取的代碼應該是這個樣子:

int count = 0; 
    while (count < size) { 
     int bytesRead = is.read(bytes, count, bytes.length - count); 
     if (bytesRead == -1) { 
      throw EOFException("didn't get a complete file"); 
     } 
     count += bytesRead; 
    } 

最後:

  • 讀取文件內容爲字節數組,在兩端浪費內存,並且準備對於一個非常大的文件來說是有問題的。

  • 你真的應該使用「試用資源」來確保所有的流都被正確關閉。手工操作繁瑣,可能會導致資源泄漏。

+0

謝謝。當我修改代碼時,只有一個模式(另一端是DataInputStream和DataOutputStream)在服務器和客戶端發送和接收文件,它工作。我使用另一端的DataOutputStream.writeUTF()和readUTF()來發送字符串。 – xpg94

1

可以使用DataOutputStream類直接寫入使用writeUTF輸出流的一些字符串(消息)( )功能。然後你可以使用readUTF()方法使用DataInputStream類的對象接收消息。

u能以下發送使用數據: -

String message="something"; 
DataOutputStream out=new DataOutputStream(socket.getOutputStream()); 
out.writeUTF(message); 

和U可以接收數據或消息使用以下內容: -

DataInputStream in=new DataInputStream(socket.getInputStream()); 
String message=in.readUTF(); 

我基本上使用這些方法來讀取從輸入流數據和寫數據輸出流多次,它每次都工作,所以你也應該檢查這種方式。

1

我想提出一個程序,它需要一個文件,並通過插座將其發送給客戶端。客戶端收到它並將其保存到文件中。這就是它應該做的。

如果您有沒有必要檢查正通過,通過什麼樣的內容,那麼直InputStreamOutputStream都去,在我看來的方式。代碼簡單快速,因爲它避免了由檢查內容進行編碼等的高級流類型所帶來的任何開銷。這也減少了破壞信息的機會。

我與斯蒂芬C'S答案達成一致,除了

讀取文件內容爲字節數組,在兩端浪費內存,並且將成爲一個真正的大文件的問題。

由於只需將一個文件移動到另一個系統而無需查看這些值,因此如果您知道如何處理內容,則這不是問題。基本流程是

client: InputStream in = getFileInputStream(); 
     OutputStream out = socket.getOutputStream(); 
     byte[] bytes = new byte[BUFFER_SIZE]; // could be anything 
     int bytesRead; 
     while((bytesRead = in.read(bytes)) != -1){ 
      out.write(bytes,0,bytesRead); 
     } 
     in.close(); 
     out.close(); 

server: InputStream in = socket.getInputStream(); 
     OutputStream out = getFileOutputStream(); 
     // the rest is the exact same thing as the client 

這將處理任何大小的文件,只受服務器的磁盤大小的限制。

這是我鞭打的一個例子。無可否認,這是很冒險的(例如使用FILE_COUNTERSTOP_KEY),但我只是試圖展示讓用戶輸入文件然後在客戶端和服務器之間發送的各個方面。

public class FileSenderDemo { 

    private static final int PORT = 7999; 
    private static final String STOP_KEY = "server.stop"; 

    private static final int[] FILE_COUNTER = {0}; 

    public static void main(String[] args) { 

     FileSenderDemo sender = new FileSenderDemo(); 

     Thread client = new Thread(sender.getClient()); 
     Thread server = new Thread(sender.getServer()); 

     server.start(); 
     client.start(); 
     try { 
      server.join(); 
      client.join(); 
     } catch (InterruptedException e) { 
      FILE_COUNTER[0] = 999 ; 
      System.setProperty(STOP_KEY,"stop"); 
      throw new IllegalStateException(e); 
     } 
    } 

    public void send(File f, OutputStream out) throws IOException{ 
     try(BufferedInputStream in = new BufferedInputStream(new FileInputStream(f),1<<11)){ 
      byte[] bytes = new byte[1<<11]; 
      int bytesRead; 
      while((bytesRead = in.read(bytes)) != -1){ 
       out.write(bytes,0,bytesRead); 
      } 
     } 
    } 

    public Runnable getClient() { 
     return() -> { 
      while(FILE_COUNTER[0] < 3 && System.getProperty(STOP_KEY) == null) { 
       Socket socket; 
       try { 
        socket = new Socket("localhost", PORT); 
       } catch (IOException e) { 
        throw new IllegalStateException("CLIENT: Can't create the client: " + e.getMessage(), e); 
       } 

       File f = getFile(); 

       try (BufferedOutputStream out = new BufferedOutputStream(socket.getOutputStream())) { 
        send(f, out); 
       } catch (IOException e) { 
        System.out.println("CLIENT: Failed to send file " + f.getAbsolutePath()+" due to: " + e.getMessage()); 
        e.printStackTrace(System.err); 
       } finally { 
        FILE_COUNTER[0]++; 
       } 
      } 
      System.setProperty(STOP_KEY,"stop"); 
     }; 
    } 

    public File getFile(){ 
     Scanner scanner = new Scanner(System.in); 
     System.out.println("CLIENT: Enter a file Name: "); 
     return new File(scanner.next()); 
    } 

    public Runnable getServer(){ 
     return() -> { 
      OutputStream out = null; 
      try{ 
       ServerSocket server = new ServerSocket(PORT); 
       server.setSoTimeout(20000); 
       while(System.getProperty(STOP_KEY) == null){ 
        Socket socket = null; 
        try { 
         socket = server.accept(); 
        }catch (SocketTimeoutException e){ 
         System.out.println("SERVER: Waited 20 seconds for an accept. Now checking if we need to stop."); 
         continue; 
        } 
        String fileName = "receivedFile_"+System.currentTimeMillis()+".content"; 
        File outFile = new File(fileName); 
        out = new BufferedOutputStream(new FileOutputStream(outFile)); 
        InputStream in = socket.getInputStream(); 
        int bytesRead; 
        byte[] bytes = new byte[1<<12]; 
        while((bytesRead = in.read(bytes)) != -1){ 
         out.write(bytes,0,bytesRead); 
        } 
        out.close(); 
        socket.close(); 
        System.out.println("SERVER: Just created a new file: " + outFile.getAbsolutePath()); 
       } 
       System.out.println("SERVER: " + STOP_KEY + " was not null, so quit."); 
      }catch (IOException e){ 
       throw new IllegalStateException("SERVER: failed to receive the file content",e); 
      }finally { 
       if(out != null){ 
        try{out.close();}catch (IOException e){} 
       } 
      } 
     }; 
    } 
} 
相關問題