Large file transfer with sockets

一个人想着一个人 提交于 2019-12-17 17:59:37

问题


When I'm transferring a large file using socket programming, the received file is incomplete i.e. it is an mp3 file which when i play sounds weird. The code is:

Server side:

File myFile = new File("abc.mp3");
{
    Socket sock = servsock.accept();
    int packetsize=1024;
    double nosofpackets=Math.ceil(((int) myFile.length())/packetsize);
    BufferedInputStream bis = new BufferedInputStream(new FileInputStream(myFile));
    for(double i=0;i<nosofpackets+1;i++) {
        byte[] mybytearray = new byte[packetsize];
        bis.read(mybytearray, 0, mybytearray.length);
        System.out.println("Packet:"+(i+1));
        OutputStream os = sock.getOutputStream();
        os.write(mybytearray, 0,mybytearray.length);
        os.flush();
    }
}

Client side:

int packetsize=1024;
FileOutputStream fos = new FileOutputStream("zz.mp3");
BufferedOutputStream bos = new BufferedOutputStream(fos);
double nosofpackets=Math.ceil(((int) (new File("abc.mp3")).length())/packetsize);
for(double i=0;i<nosofpackets+1;i++)
{
    InputStream is = sock.getInputStream();
    byte[] mybytearray = new byte[packetsize];
    int bytesRead = is.read(mybytearray, 0,mybytearray.length );
    System.out.println("Packet:"+(i+1));
    bos.write(mybytearray, 0,mybytearray.length);
}
sock.close();
bos.close();

On the Client side I have used new File("abc.mp3")).length just for simplicity (I could send the length of the file from the server side).

This code works perfectly if client and server are the same machine, but the file gets distorted if they are on different machines.


回答1:


The canonical way to copy a stream in Java:

int count;
byte[] buffer = new byte[8192];
while ((count = in.read(buffer)) > 0)
{
  out.write(buffer, 0, count);
}

Works with any buffer size greater than zero. The temptation to relate the buffer size to the input size should be strenuously avoided.




回答2:


I think that the problem is that you are ignoring the values returned by various read calls, and assuming they completely fill the buffer. This is problematic:

  • When reading from a file, the last read probably won't fill the buffer.

  • When reading from a socket, any read may return before filling the buffer.

The net result that your writes will put junk into the stream (at the server end), and into the destination file (at the client end).

Furthermore, it is pointless dividing the file up into chunks based on the size of the file. Just read until you get to the end of file.




回答3:


Don't reinvent the wheel, use IOUtils.copy().




回答4:


Don't use packets.
Try using the ByteArrayOutputStream instead of using the static byte array.
keep reading from the inputstream until u reach EOF. n write each of this to the ByteArrayOutputStream.


InputStream is = sock.getInputStream();
ByteArrayOutputStream baos = new ByteArrayOutputStream();
int byteToBeRead = -1;
while((byteToBeRead = is.read())!=-1){
baos.write(byteToBeRead);
}
byte[] mybytearray = baos.toByteArray();
bos.write(mybytearray, 0,mybytearray.length);

Hope this helps.



来源:https://stackoverflow.com/questions/5113914/large-file-transfer-with-sockets

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!