Search code examples
javamultithreadingserverclientimageicon

Java - Error Sending ImageIcons from server to client via ObjectOutputStream read/writeObject()


Little background, currently trying to complete an assignment for my degree, trying to implement an 'Auction House' localhost server-client program in which clients can bid on items saved on the server. When a new client connects to the server the user has to register his/her name and then the server will send the client all the item information.

Currently all the other information sends correctly however when I try to send the images of the items to the clients via ObjectOutputStream the server always fails to send the ImageIcons, when I then disconnect the client I am met with this error message:

    Exception in thread "main" java.io.StreamCorruptedException: invalid type code: 53 at java.io.ObjectInputStream.readObject0(Unknown Source)
   at java.io.ObjectInputStream.readObject(Unknown Source)
   at AuctionClient.retrieveItemInformation(AuctionClient.java:365)
   at AuctionClient.main(AuctionClient.java:341)

I think it might have something to do with that Im trying to send ImageIcons directly through the output stream without utilising serialisable but our java lecturer told us that ImageIcon didn't require that to function properly so i'm unsure, any advice would be great! I will place the code for server/clients below!

Server thread code:

public ClientHandler(Socket socket, BiddingItem item1, BiddingItem item2, int number) throws IOException
{
    client = socket;
    outputImage = new ObjectOutputStream(client.getOutputStream());
    input = new Scanner(client.getInputStream());
    output = new PrintWriter(client.getOutputStream(), true);
    startedItem1 = item1;
    startedItem2 = item2;
    clientNumber = number;
    images = new ImageIcon[2];
    images[0] = startedItem1.getImage();
    images[1] = startedItem2.getImage();
}

Trying to send information to client:

public void run()
{
    //previous code...
    for (int i=0; i<images.length;++i)
    {
        try 
        {
            outputImage.writeObject(images[i]);
        }
        catch (IOException ioEx)
        {
            System.out.println("\n**ERROR: Unable to send Item " + i + " image to client!**");
        }
        try 
        {
            outputImage.flush();
        } 
        catch (IOException e1) 
        {
            System.out.println("\n**ERROR: Unable to flush OutputObjectStream!**");
        }
    }

Client creating input stream:

public static void main(String[] args) throws IOException, InterruptedException, ClassNotFoundException 
{
    //previous code
    try
    {
        txtBoxServerMessage.setText("CLIENT: Attempting to connect to server...");
        Thread.sleep(2000);
        socket = new Socket(host, PORT);
        inputFromServer = new Scanner(socket.getInputStream());
        inputImageFromServer = new ObjectInputStream(socket.getInputStream());
        outputToServer = new PrintWriter(socket.getOutputStream(), true);
    }
    catch(IOException ioEx)
    {
        txtBoxServerMessage.setText("CLIENT-ERROR: Unable to connect to server! Exiting...");
        Thread.sleep(2000);
        System.exit(1);
    }
}

Function that client uses to accept information:

private static void retrieveItemInformation() throws InterruptedException, ClassNotFoundException, IOException
{
    txtBoxServerMessage.setText("CLIENT: Waiting for Item Information...");
    Thread.sleep(3000);

    clientNumber = Integer.parseInt(inputFromServer.nextLine());

    item1Code = inputFromServer.nextLine();
    item1Desc = inputFromServer.nextLine();
    item1Deadline = inputFromServer.nextLine();
    item1AuctionValue = Double.parseDouble(inputFromServer.nextLine());

    item2Code = inputFromServer.nextLine();
    item2Desc = inputFromServer.nextLine();
    item2Deadline = inputFromServer.nextLine();
    item2AuctionValue = Double.parseDouble(inputFromServer.nextLine());

    item1Image = (ImageIcon)inputImageFromServer.readObject(); // READING IMAGE 1
    item2Image = (ImageIcon)inputImageFromServer.readObject(); // READING IMAGE 2

    txtBoxServerMessage.setText("DEBUG: FINISHED IMAGE");
    txtBoxServerMessage.setText("CLIENT: Information Recieved! Displaying...");
    Thread.sleep(1000);
    comboItemSelect.addItem(item1Code);
    comboItemSelect.addItem(item2Code);
    txtBoxClientNumber.setText(String.valueOf(clientNumber));

    updateDisplay();

}

Cheers!

M


Solution

  • The problem is this:

    outputImage = new ObjectOutputStream(client.getOutputStream());
    // ...
    output = new PrintWriter(client.getOutputStream(), true);
    

    You can't wrap a single OutputStream in two different wrappers. Their individual states and buffering are not compatible.

    In particular, if you write even a single byte using anything other than your ObjectOutputStream, the object stream is corrupted.

    If you want to send both objects and text, you can write a String object to the ObjectOutputStream. You also can call ObjectOutputStream.writeUTF directly.