Search code examples
javaimagesocketsoutputstream

I just send parts of the image through socket using Java


I used the code from Here as below and got only half of the picture sent, could anybody tell me the reason? The code to get the size and read the size is too complex to me so I couldn't figure it out.

public class Send {

public static void main(String[] args) throws Exception {
    Socket socket = new Socket("localhost", 13085);
    OutputStream outputStream = socket.getOutputStream();

    BufferedImage image = ImageIO.read(new File("C:\\Users\\Jakub\\Pictures\\test.jpg"));

    ByteArrayOutputStream byteArrayOutputStream = new ByteArrayOutputStream();
    ImageIO.write(image, "jpg", byteArrayOutputStream);

    byte[] size = ByteBuffer.allocate(4).putInt(byteArrayOutputStream.size()).array();
    outputStream.write(size);
    outputStream.write(byteArrayOutputStream.toByteArray());
    outputStream.flush();
    System.out.println("Flushed: " + System.currentTimeMillis());

    Thread.sleep(120000);
    System.out.println("Closing: " + System.currentTimeMillis());
    socket.close();
}
}


public class Receive {

public static void main(String[] args) throws Exception {
    ServerSocket serverSocket = new ServerSocket(13085);
    Socket socket = serverSocket.accept();
    InputStream inputStream = socket.getInputStream();

    System.out.println("Reading: " + System.currentTimeMillis());

    byte[] sizeAr = new byte[4];
    inputStream.read(sizeAr);
    int size = ByteBuffer.wrap(sizeAr).asIntBuffer().get();

    byte[] imageAr = new byte[size];
    inputStream.read(imageAr);

    BufferedImage image = ImageIO.read(new ByteArrayInputStream(imageAr));

    System.out.println("Received " + image.getHeight() + "x" + image.getWidth() + ": " + System.currentTimeMillis());
    ImageIO.write(image, "jpg", new File("C:\\Users\\Jakub\\Pictures\\test2.jpg"));

    serverSocket.close();
}
} 

As @EJP commented,the most possible problem is that in the receive part,the inputStream.read(byte[] byteArray) can not fully load the byteArray. And if I use DataInputStream dis=new DataInputStream(inputStream) then call dis.readFully(byteArray) it would load the byteArray. Though I couldn't figure out the reason why inputStream won't work. Hopefully some one could show the reason, which would be well appreciated. The corrected code is as follow:

public class Send {

public static void main(String[] args) throws Exception {
Socket socket = new Socket("localhost", 13085);
OutputStream outputStream = socket.getOutputStream();

BufferedImage image = ImageIO.read(new File("test.jpg"));

ByteArrayOutputStream byteArrayOutputStream = new ByteArrayOutputStream();
ImageIO.write(image, "jpg", byteArrayOutputStream);

byte[] size = ByteBuffer.allocate(4).putInt(byteArrayOutputStream.size()).array();
outputStream.write(size);
outputStream.write(byteArrayOutputStream.toByteArray());
outputStream.flush();
System.out.println("Flushed: " + System.currentTimeMillis());

Thread.sleep(120000);
System.out.println("Closing: " + System.currentTimeMillis());
socket.close();
}
}

public class Receive {

public static void main(String[] args) throws Exception {
ServerSocket serverSocket = new ServerSocket(13085);
Socket socket = serverSocket.accept();
InputStream inputStream = socket.getInputStream();
DataInputStream dataInputStream=new DataInputStream(inputStream);

System.out.println("Reading: " + System.currentTimeMillis());

byte[] sizeAr = new byte[4];
dataInputStream.read(sizeAr);
int size = ByteBuffer.wrap(sizeAr).getInt();

byte[] imageAr = new byte[size];
dataInputStream.readFully(imageAr);
BufferedImage image = ImageIO.read(new ByteArrayInputStream(imageAr));

System.out.println("Received " + image.getHeight() + "x" + image.getWidth() + ": " + System.currentTimeMillis());
ImageIO.write(image, "jpg", new File("received.jpg"));

serverSocket.close();
}
}

Solution

  • Get rid of the byte array streams and do the ImageIO direct with the socket streams.

    The problem is that you are assuming that read() fills the buffer, but if you do as above you will get rid of that read() completely anyway.

    Sending the length is also pointless as you're closing them socket afterwards anyway. The end of stream is sufficient to delimit the image.

    Get rid of the sleep as well. You don't need sleeps in network code.