2016-12-28 60 views
0

我試圖創建一個客戶端/服務器程序,允許服務器和客戶端向對方發送文件。我創建了套接字,並將客戶端連接到服務器。我現在正在爲這臺計算機做同一臺計算機。如果它完善了,我會把它帶到另一臺電腦上試試。通過java socket編程共享的文件最終在接收端被破壞

我的問題是,文件傳輸成功,但它已損壞。收到的文件已損壞,但原文沒問題。我發生套接字異常的問題,在套接字發送文件後不斷重置,但我設法解決這個問題。現在文件已發送,但尚未完成。

收到的文件大小小於發送文件的大小,這導致收到的文件無法正常工作。我通過網絡發送了一個pdf文件。原文約爲695kb,但收到的文件爲688kb,導致文件被損壞。我也嘗試發送視頻,並得到相同的結果。接收到的文件比發送的文件小。

我檢查了程序,但是我看不到問題來自哪裏。 我試圖實現的發送方法是零拷貝方法,其中來自文件的數據直接發送到套接字,從它直接讀取到文件的位置。在將它發送到輸出流之前,我沒有使用存儲在緩衝區中的其他方法。這是因爲我想能夠使用該程序發送大文件。大文件將填滿java堆內存,此外此方法更快。

緩衝方法:

.... 
File file = new File("path to file); 
BufferedInputStream = new BufferedInputStream(new FileInputStream(file)); 
BufferedOutputStream out = new  BufferedOutputStream(socket.getOutputStream()); 

byte[] buf = new byte[length]; 
in.read(buf, 0, buf.length); 
out.write(buf, 0, buf.length); 
.... 

我沒有用這個緩衝區方法。這是我的代碼。這是文件服務器

import java.io.*; 
import java.net.*; 

import javax.swing.JFileChooser; 

public class ShareServer { 

    public static void main(String args[]) { 
     int port = 4991; 
     ServerSocket server; 
     Socket socket = null; 
     BufferedInputStream in = null; 
     BufferedOutputStream out = null; 

     try { 
      server = new ServerSocket(port); 
      System.out.println("Waiting for connection request.."); 

      socket = server.accept(); 

      System.out.println("Connected to " + socket.getInetAddress().getHostName()); 

      JFileChooser fc = new JFileChooser(); 
      File file = null; 

      if (fc.showOpenDialog(null) == JFileChooser.APPROVE_OPTION) 
       file = fc.getSelectedFile(); 

      // send out the reference of the file using writeObject() method 
      new ObjectOutputStream(socket.getOutputStream()).writeObject(file); 

      in = new BufferedInputStream(new FileInputStream(file)); 
      out = new BufferedOutputStream(socket.getOutputStream()); 

      // send file 
      int b = 1; 
      while (b != -1){ 
       b = in.read(); 
       out.write(b); 
      } 

      System.out.println(file.getName() + " has been sent successfully!"); 

     } catch (Exception e) { 
      System.out.println(e.getMessage()); 
      e.printStackTrace(); 
     } 

     try { 
      in.close(); 
      out.close(); 
      socket.close(); 

     } catch (Exception e) { 
      e.printStackTrace(); 
     } 
    } 
} 

這裏是Client類:

import java.io.*; 
import java.net.*; 

import javax.swing.JOptionPane; 

public class ShareClient { 
    public ShareClient() { 

    } 

    public static void main(String[] args) throws IOException, ClassNotFoundException { 

     String host = InetAddress.getLocalHost().getHostAddress(); 

     Socket socket = new Socket(host, 4991); 
     System.out.println("Connected to " + host); 

     // receive the file object. this does not contain the file data 
     File refFile = (File) new ObjectInputStream(socket.getInputStream()).readObject(); 

     System.out.println("File to receive " + refFile.getName()); 

     // create a new file based on the refFile 
     File newFile = new File(System.getProperty("user.home") + "/desktop/ReceivedFiles", refFile.getName()); 

     BufferedInputStream in = new BufferedInputStream(socket.getInputStream()); 
     BufferedOutputStream out = new BufferedOutputStream(new FileOutputStream(newFile)); 

     System.out.println("Receiving file now..."); 

     int b; 
     while ((b = in.read()) != -1) 
      out.write(b); 

     System.out.println("File has been received successfully!"); 

     socket.close(); 

    } 

} 

的服務器和客戶端類的成功運行沒有任何異常,並且該文件被髮送,但它已損壞。它是不完整的。 請注意,通過ObjectInput和ObjectOutput流發送的文件不是真實文件,而只是一個文件對象,它具有我要發送的filie的所有信息,但不包含文件的二進制數據。

請問有人可以幫我嗎?爲什麼文件損壞或不完整?它被讀到最後(當-1)被返回時,並且所有的字節被髮送,但由於某些原因,我不能解釋,它最終小於原始文件的大小。

回答

1

當前,您在文件末尾寫入-1(即應該停止時)。喜歡的東西,

int b = 1; 
while (b != -1){ 
    b = in.read(); 
    if (b != -1) { 
     out.write(b); 
    } 
} 

int b; 
while ((b = in.read()) != -1) { 
    out.write(b); 
} 
0

我終於得到了答案的問題!這非常簡單!緩衝區。我只是添加了一小段代碼來刷新服務器中的套接字輸出流緩衝區,並在客戶端程序中刷新fileoutputstream緩衝區,就是這樣!看起來有些字節的數據留在緩衝區中,導致文件不完整。這是緩衝輸入和輸出的問題之一。如果你忘記刷新緩衝區,你開始遇到問題。

下面的代碼:

int b = 1; 
while(b != -1){ 
    out.write(b); 
} 
out.flush(); //this solved my problem. I also did it in the client class 

非常感謝你的回答@Elliot弗裏希:)

相關問題