2013-07-15 31 views
1

我想寫一個相當複雜的java服務器上傳系統。我在下面列出的兩個小程序中重現了錯誤。基本上,我使用ObjectOutputStream/ObjectInputStream通過客戶機/服務器進行通信。這是一個要求;在這個ObjectOutputStream/ObjectInputStream設置中,我有數千行代碼完美地工作,所以我必須能夠在上傳完成後仍然使用這些流。問題發送字節數組在java中objectoutputstream

訪問文件(讀取客戶端上的一個和一個在服務器上寫的),和的FileInputStream FileOutputStream中被使用。我的客戶出現完美運作;它讀取文件並在每次迭代中發送一​​個不同的字節數組(每次讀取1MB,因此可以處理大型文件而不會溢出堆)。但是,在服務器上,看起來好像字節數組總是隻是第一個發送的數組(文件的第一個1MB)。這不符合我對ObjectInputStream/ObjectOutputStream的理解。我正在尋求這個問題的解決方案,或者就此問題進行足夠的教育,以形成我自己的解決方案。

下面是客戶端代碼:

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

public class stupidClient 
{ 
    public static void main(String[] args) 
    { 
    new stupidClient(); 
    } 

    public stupidClient() 
    { 
    try 
    { 
     Socket s = new Socket("127.0.0.1",2013);//connect 
     ObjectOutputStream output = new ObjectOutputStream(s.getOutputStream());//init stream 

     //file to be uploaded 
     File file = new File("C:\\Work\\radio\\upload\\(Op. 9) Nocturne No. 1 in Bb Minor.mp3"); 
     long fileSize = file.length(); 
     output.writeObject(file.getName() + "|" + fileSize);//send name and size to server 

     FileInputStream fis = new FileInputStream(file);//open file 
     byte[] buffer = new byte[1024*1024];//prepare 1MB buffer 
     int retVal = fis.read(buffer);//grab first MB of file 
     int counter = 0;//used to track progress through upload 

     while (retVal!=-1)//until EOF is reached 
     { 
     System.out.println(Math.round(100*counter/fileSize)+"%");//show current progress to system.out 
     counter += retVal;//track progress 

     output.writeObject("UPACK "+retVal);//alert server upload packet is incoming, with size of packet read 

     System.out.println(""+buffer[0]+" "+buffer[1]+" "+buffer[2]);//preview first 3 bytes being sent 
     output.writeObject(buffer);//send bytes 
     output.flush();//make sure all bytes read are gone 

     retVal = fis.read(buffer);//get next MB of file 
     } 
     System.out.println(Math.round(100*counter/fileSize)+"%");//show progress at end of file 
     output.writeObject("UPLOAD_COMPLETE");//let server know protocol is finished 
     output.close(); 
    } 
    catch (Exception e) 
    { 
     e.printStackTrace(); 
    } 
    } 
} 

以下是我的服務器代碼:

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

public class stupidServer 
{ 
    Socket s; 
    ServerSocket server; 

    public static void main(String[] args) 
    { 
    new stupidServer(); 
    } 

    public stupidServer() 
    { 
    try 
    { 
     //establish connection and stream 
     server = new ServerSocket(2013); 
     s = server.accept(); 
     ObjectInputStream input = new ObjectInputStream(s.getInputStream()); 
     String[] args = ((String)input.readObject()).split("\\|");//args[0] will be file name, args[1] will be file size 
     String fileName = args[0]; 
     long filesize = Long.parseLong(args[1]); 

     String upack = (String)input.readObject();//get upload packet(string reading UPACK [bytes read]) 
     FileOutputStream outStream = new FileOutputStream("C:\\"+fileName.trim()); 

     while (!upack.equalsIgnoreCase("UPLOAD_COMPLETE"))//until protocol is complete 
     { 
     int bytes = Integer.parseInt(upack.split(" ")[1]);//get number of bytes being written 
     byte[] buffer = new byte[bytes]; 
     buffer = (byte[])input.readObject();//get bytes sent from client 

     outStream.write(buffer,0,bytes);//go ahead and write them bad boys to file 
     System.out.println(buffer[0]+" "+buffer[1]+" "+buffer[2]);//peek at first 3 bytes received 
     upack = (String)input.readObject();//get next 'packet' - either another UPACK or a UPLOAD_COMPLETE 
     } 
     outStream.flush(); 
     outStream.close();//make sure all bytes are in file 
     input.close();//sign off 
    } 
    catch (Exception e) 
    { 
     e.printStackTrace(); 
    } 
    } 
} 

與往常一樣,非常感謝您的時間!

回答

3

你的眼前的問題是,ObjectOutputStream使用的ID的機制來避免多次發送相同的對象通過該流。客戶端將發送此ID用於buffer的第二次和隨後寫入,並且服務器將使用其緩存值。

解決這個迫在眉睫的問題是添加一個調用reset()

output.writeObject(buffer);//send bytes 
output.reset(); // force buffer to be fully written on next pass through loop 

這且不說,你通過在它們上面分層自己的協議濫用對象流。例如,將文件名和文件大小寫爲由「|」分隔的單個字符串;只需將它們寫成兩個單獨的值即可。同上每個寫入的字節數。

+0

完全解決了這個問題。我不知道發送的對象被緩存了,我還有更多的閱讀要做....非常感謝您的幫助! – bowens

相關問題