2013-07-15 34 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

相关问题