Large file transfer with sockets

When I transfer a large file using socket programming, the resulting file is incomplete, i.e. This is an mp3 file that, when I play, sounds strange. Code:

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 used new File("abc.mp3")).length only for simplicity (I could send the length of the file from the server side).

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

+4
source share
4 answers

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 associate the buffer size with the input size should be avoided.

+17
source

I think 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 will probably not fill the buffer.

  • When reading from a socket, any reading can return before the buffer is full.

As a result, your records will be placed in the stream (at the end of the server) and in the target file (on the client side).

In addition, it makes no sense to divide the file into pieces based on the size of the file. Just read until you get to the end of the file.

+8
source

Do not reinvent the wheel, use IOUtils.copy() .

+5
source

Do not use packages.
Try using ByteArrayOutputStream instead of using a static byte array.
keep reading from the input until you reach EOF. n write each of them to 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.

0
source

Source: https://habr.com/ru/post/1341257/


All Articles