Reputation: 31
I've managed to send small (less than about 22mb) images but when sending bigger images I get errors such as shown below. I want to be able to reuse the socket and therefore not closing it.
As you maybe can see I'm trying to send a picture from client to server where it will be displayed if i type s in the console.
javax.imageio.IIOException: Error reading PNG image data
at java.desktop/com.sun.imageio.plugins.png.PNGImageReader.readImage(Unknown Source)
at java.desktop/com.sun.imageio.plugins.png.PNGImageReader.read(Unknown Source)
at java.desktop/javax.imageio.ImageIO.read(Unknown Source)
at java.desktop/javax.imageio.ImageIO.read(Unknown Source)
at lärning5.Server.main(Server.java:55)Caused by: java.io.EOFException: Unexpected end of ZLIB input stream
at java.base/java.util.zip.InflaterInputStream.fill(Unknown Source)
at java.base/java.util.zip.InflaterInputStream.read(Unknown Source)
at java.base/java.io.BufferedInputStream.fill(Unknown Source)
at java.base/java.io.BufferedInputStream.read1(Unknown Source)
at java.base/java.io.BufferedInputStream.read(Unknown Source)
at java.base/java.io.DataInputStream.readFully(Unknown Source)
at java.desktop/com.sun.imageio.plugins.png.PNGImageReader.decodePass(Unknown Source)
at java.desktop/com.sun.imageio.plugins.png.PNGImageReader.decodeImage(Unknown Source)
... 5 more
I have tried sending the images as an object using ObjectOutputStream
which ended up requiring the socket to close. I have also tried scaling up the buffers so they can should be able to accommodate this much memory. I have tried using ByteArrayInputStream
and ByteArrayOutputStream
"the right way" in which I pickup exactly the size of the ByteArray
and I always end up with the same error message.
Try to ignore the comments
Server code
package lärning5;
import java.awt.Toolkit;
import java.awt.image.BufferedImage;
import java.io.ByteArrayInputStream;
import java.io.File;
import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
import java.net.InetAddress;
import java.net.ServerSocket;
import java.net.Socket;
import java.net.UnknownHostException;
import java.util.Scanner;
import javax.imageio.ImageIO;
import javax.imageio.stream.ImageInputStream;
import javax.imageio.stream.ImageOutputStream;
import javax.swing.JFrame;
import javax.swing.JPanel;
public class Server
{
static ServerSocket servern;
static Socket client = new soketen();
static OutputStream out;
static InputStream in;
static JFrame fön = new JFrame();
static Panelen pan = new Panelen();
static BufferedImage picture;
static Scanner read = new Scanner(System.in);
public static void main(String args[])
{
try
{
servern = new ServerSocket(7777, 9999);
client = servern.accept();
System.out.print("conectad");
out = client.getOutputStream();
out.flush();
in = client.getInputStream();
byte[] buffer = new byte[899999];
in.read(buffer, 0, buffer.length);
ByteArrayInputStream bil = new ByteArrayInputStream(buffer, 0, buffer.length);
picture = ImageIO.read(bil);
} catch (Exception e)
{
System.out.print("gg wp ");
e.printStackTrace();
}
if (read.nextLine().equals("s"))
{
fön.setSize(Toolkit.getDefaultToolkit().getScreenSize().width, Toolkit.getDefaultToolkit().getScreenSize().height);
fön.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
fön.add(pan);
fön.repaint();
fön.setVisible(true);
}
}
}
Client code
package lärning6;
import java.awt.Rectangle;
import java.awt.Robot;
import java.awt.Toolkit;
import java.awt.image.BufferedImage;
import java.awt.image.RenderedImage;
import java.io.ByteArrayOutputStream;
import java.io.File;
import java.io.InputStream;
import java.io.OutputStream;
import java.net.InetAddress;
import java.net.Socket;
import java.util.ArrayList;
import java.util.List;
import javax.imageio.ImageIO;
import javax.imageio.stream.ImageInputStream;
import javax.imageio.stream.ImageOutputStream;
public class Client
{
static Socket servern;
static OutputStream out;
static InputStream in;
static Robot datorn;
static BufferedImage picture;
static ImageInputStream bil;
static File fil = new File("src\\bilder\\ddeee.PNG");
public static void main(String args[])
{
try
{
servern = new Socket(InetAddress.getByName("the ip address"), 7777);
out = servern.getOutputStream();
out.flush();
in = servern.getInputStream();
//byte[] buffer = new byte[90000];
ByteArrayOutputStream bil = new ByteArrayOutputStream();
picture = ImageIO.read(fil);//datorn.createScreenCapture(new Rectangle(0, 0, 500, 500));
ImageIO.write(bild, "PNG", bil);
out.write(bil.toByteArray());
/*
bil = ImageIO.createImageInputStream(picture);
//bil.read(buffer, 0, buffer.length);
ImageOutputStream bil = null;
ImageIO.write(picture, "png", bil);
buffer = bil.*/
}catch(Exception e)
{
System.out.print("gg wr");
e.printStackTrace();
}
}
}
Panel
package lärning5;
import java.awt.Graphics;
import javax.swing.JPanel;
public class Panelen extends JPanel
{
public void paintComponent(Graphics g)
{
g.drawImage(Server.picture, 0, 0, this.getWidth(), this.getHeight(), null);
}
}
THE CODE ABOVE AND THE CODE BELOW ARE TWO DIFFERENT CODES AND SHOULD NOT BE COMBINED
The code below is the codes which use bufferers that adapt to the picture size.
Server
package lärning5;
import java.awt.Toolkit;
import java.awt.image.BufferedImage;
import java.io.ByteArrayInputStream;
import java.io.File;
import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
import java.net.InetAddress;
import java.net.ServerSocket;
import java.net.Socket;
import java.net.UnknownHostException;
import java.nio.ByteBuffer;
import java.util.Scanner;
import javax.imageio.ImageIO;
import javax.imageio.stream.ImageInputStream;
import javax.imageio.stream.ImageOutputStream;
import javax.swing.JFrame;
import javax.swing.JPanel;
public class Server
{
static ServerSocket servern;
static Socket client = new soketen();
static OutputStream out;
static InputStream in;
static JFrame window = new JFrame();
static Panelen panel = new Panelen();
static BufferedImage bild;
static File fil = new File("src\\bilde\\bilden.jpg");
static Scanner läs = new Scanner(System.in);
public static void main(String args[])
{
try
{
servern = new ServerSocket(7777, 9999);
client = servern.accept();
System.out.print("conectad");
out = client.getOutputStream();
out.flush();
in = client.getInputStream();
byte[] buffer = new byte[4];
//in.read(buffer);
//ImageOutputStream bil = ImageIO.createImageOutputStream(bild);
in.read(buffer);
byte[] buffer2 = new byte[ByteBuffer.wrap(buffer).asIntBuffer().get()];
in.read(buffer2);
ImageIO.write(ImageIO.read(new ByteArrayInputStream(buffer2)), "PNG", new File("C:\\Users\\Bodi\\Desktop\\testse"));
bild = ImageIO.read(new ByteArrayInputStream(buffer2));
} catch (Exception e)
{
System.out.print("gg wp ");
e.printStackTrace();
}
if (läs.nextLine().equals("s"))
{
window.setSize(Toolkit.getDefaultToolkit().getScreenSize().width, Toolkit.getDefaultToolkit().getScreenSize().height);
window.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
window.add(panel);
window.repaint();
window.setVisible(true);
}
}
}
Client
package lärning6;
import java.awt.Rectangle;
import java.awt.Robot;
import java.awt.Toolkit;
import java.awt.image.BufferedImage;
import java.awt.image.RenderedImage;
import java.io.ByteArrayOutputStream;
import java.io.File;
import java.io.InputStream;
import java.io.OutputStream;
import java.net.InetAddress;
import java.net.Socket;
import java.nio.ByteBuffer;
import java.util.ArrayList;
import java.util.List;
import javax.imageio.ImageIO;
import javax.imageio.stream.ImageInputStream;
import javax.imageio.stream.ImageOutputStream;
public class Client
{
static Socket servern;
static OutputStream out;
static InputStream in;
static Robot datorn;
static BufferedImage picture;
static ImageInputStream bil;
static File fil = new File("src\\bilder\\dddd.PNG");
public static void main(String args[])
{
try
{
servern = new Socket(InetAddress.getByName("The ip adress"), 7777);
out = servern.getOutputStream();
out.flush();
in = servern.getInputStream();
//byte[] buffer = new byte[90000];
ByteArrayOutputStream bil = new ByteArrayOutputStream();
picture = ImageIO.read(fil);//datorn.createScreenCapture(new Rectangle(0, 0, 500, 500));
ImageIO.write(picture, "PNG", bil);
byte[] storlek = ByteBuffer.allocate(4).putInt(bil.size()).array();
out.write(storlek);
out.write(bil.toByteArray());
out.flush();
/*
bil = ImageIO.createImageInputStream(picture);
//bil.read(buffer, 0, buffer.length);
ImageOutputStream bil = null;
ImageIO.write(picture, "png", bil);
buffer = bil.*/
}catch(Exception e)
{
System.out.print("gg wr");
e.printStackTrace();
}
}
}
The errors are a bit different to
Errors
conectadgg wp javax.imageio.IIOException: Error reading PNG image data
at java.desktop/com.sun.imageio.plugins.png.PNGImageReader.readImage(Unknown Source)
at java.desktop/com.sun.imageio.plugins.png.PNGImageReader.read(Unknown Source)
at java.desktop/javax.imageio.ImageIO.read(Unknown Source)
at java.desktop/javax.imageio.ImageIO.read(Unknown Source)
at lärning5.Server.main(Server.java:134)
Caused by: javax.imageio.IIOException: Unknown row filter type (= 148)!
at java.desktop/com.sun.imageio.plugins.png.PNGImageReader.decodePass(Unknown Source)
at java.desktop/com.sun.imageio.plugins.png.PNGImageReader.decodeImage(Unknown Source)
... 5 more
I expect the server to turn on smoothly without any errors and the client to run smoothly without any errors ether.
But when they connect, i expect the server to receive the byte arrays but then pop up with the errors still running but doing nothing. You should still be able to press "s", and that will bring up a blank window. But this is wrong.
What i want to actually happen is that the server receives the byte array, does it's thing and then waits for you to press "s", when you press "s", a window should pop up displaying the received image.
that actually happens if i simply change to a "smaller"(less than 22 mb) pictures.
Upvotes: 3
Views: 442
Reputation: 140633
I think your problem starts here:
in.read(buffer, 0, buffer.length)
When you turn to the javadoc for that method, it says:
RETURNS the total number of bytes read into the buffer, or -1 if there is no more data because the end of the stream has been reached.
It is absolutely essential that you check that returned number of "bytes read". 99% of the time, you get all the bytes you want. But sometimes ... less than that! And in that case, you will have less valid bytes than expected in your buffer array.
In your case, you have to tell the server how many bytes should be read overall, and then you have to read until you really read exactly that number of bytes!
Long story short: it starts with a conceptual problem. A single read into a buffer can't be sufficient to handle variable-sized data! Your server only has
byte[] buffer = new byte[899999];
But most likely, your the client will send a different number of bytes. How is the server supposed to know how many bytes exactly will be coming over the wire?!
So: change your "protocol" to first tell the server how many bytes will follow. Then ensure that exactly that number of bytes gets read! That might include some sort of loop (when the image is larger than your buffer array!)
Upvotes: 1