Hello,

I have two programs:
a) Server.java : Using a JFileChooser, selects a file and then sends it to Client.

b) Client. java: Displays the file.

My problem:
I am able to send a file from server to client only once. The ObjectOutputStream.writeObject() does not work after that.

I later learnt that ObjectOutputStream.writeObject() needs a new object for every write operation. Also, I would need to reset(). Maybe I am writing/resetting it wrong, but I am am still able to send only the first image. I will be grateful for any help.

            import java.net.*;
            import java.io.*;
            import java.awt.FlowLayout;
            import java.awt.event.ActionEvent;
            import java.awt.event.ActionListener;
            import java.io.File;
            import javax.swing.JButton;
            import javax.swing.JFileChooser;
            import javax.swing.JFrame;
            import javax.swing.JLabel;

            public class Server 
            {
                private ServerSocket serverSocket;
                private Socket socketOut;
                private FileChoose f;

                public Server(int port) 
                {
                    try 
                    {
                        serverSocket = new ServerSocket(4444);
                    } 
                    catch (IOException e) 
                    {
                        System.err.println("Could not listen on port: 4444.");
                        System.exit(-1);
                    }

                    try
                    {
                        socketOut = serverSocket.accept();
                    }
                    catch (IOException e)
                    {}

                    f = new FileChoose();

                }

                public static void main(String[] args) 
                {
                    Server s = new Server(4444);
                }

                private class FileChoose extends JFrame 
                {
                    private JButton openButton, openButton1, openButton2;
                    private String filelist = "";
                    private FileInputStream fis;
                    private ObjectOutputStream oos;

                    public FileChoose()
                    {
                        super("File Chooser Test Frame");

                        setLayout(new FlowLayout());
                        openButton = new JButton("Open");
                        openButton1 = new JButton("Send");
                        openButton2 = new JButton("Done");

                        openButton.addActionListener(
                            new ActionListener() 
                            {
                                public void actionPerformed(ActionEvent ae) 
                                {

                                    JFileChooser chooser = new JFileChooser();
                                    int option = chooser.showOpenDialog(FileChoose.this);
                                    if (option == JFileChooser.APPROVE_OPTION) 
                                    {
                                        File sf = chooser.getSelectedFile();
                                        filelist = sf.getPath();
                                        System.out.println (filelist);
                                    }
                                }
                            }
                        );

                        openButton1.addActionListener(
                            new ActionListener() 
                            {
                                public void actionPerformed(ActionEvent ae) 
                                {
                                    sendFile();

                                }
                            }
                        );
                        openButton2.addActionListener(
                            new ActionListener() 
                            {
                                public void actionPerformed(ActionEvent ae) 
                                {
                                    closeSockets();
                                }
                            }
                        );

                        try
                        {
                            oos = new ObjectOutputStream(socketOut.getOutputStream()) ;
                        }
                        catch (IOException e)
                        {}

                        add(openButton);
                        add(openButton1);
                        add(openButton2);

                        setSize(350, 200);
                        setVisible(true);
                    }

                    public void sendFile()
                    {
                        try
                        {
                            fis = new FileInputStream(new String (filelist));
                            byte[] buffer = new byte[fis.available()];
                            fis.read(buffer);
                            System.out.println ("Finished Reading into Buffer");
                            oos.writeObject(buffer);
                            oos.reset();
                            System.out.println (buffer.length);
                        }
                        catch(FileNotFoundException e)
                        {}
                        catch(IOException e)
                        {}
                    }

                    public void closeSockets()
                    {
                        try
                        {
                            socketOut.close();
                            serverSocket.close();
                        }
                        catch(IOException e)
                        {}
                    }
                }

            }


            import java.net.*;
            import java.io.*;
            import java.awt.image.*;
            import java.awt.*;
            import javax.swing.*;
            import javax.imageio.*;

            public class Client
            {
                private static Socket socket  = null;

                public static void main (String args[]) throws IOException, ClassNotFoundException
                {

                    try {
                        socket = new Socket("localhost", 4444);
                    } catch (UnknownHostException e) {
                        System.err.println("Don't know about host: localhost");
                        System.exit(1);
                    }
                    ObjectInputStream ois = new ObjectInputStream(socket.getInputStream());
                    byte[] buffer = (byte[])ois.readObject();
                    Image image = Toolkit.getDefaultToolkit().createImage(buffer); 
                    JFrame frame = new JFrame();
                    JLabel label = new JLabel(new ImageIcon(image));
                    frame.getContentPane().add(label, BorderLayout.CENTER);
                    frame.setSize(500, 500);
                    frame.setVisible(true);

                    socket.close();
                }
            }

Edited 2 Years Ago by sciprog22

The client code above reads a single byte array from the socket then closes the socket. Obviously that's not going to read multiple objects! Is there some other code you have that at least tries to read multiple objects?

ps I have plenty of working systems that send mutiple objects over a socket connection - just keep the sockets and streams open.

Hello James,

Thanks a lot for the reply! I have changed my program to handle multiple images. Its now able to read multiple images but I have the following issues:

a) Certain images are partially blocked out.
b) I am unable to see certain images (just comes up with an empty JFrame), especially if they are small images. The large images work fine.

I would be grateful for any help.

My programs are as below:

import java.net.*;
import java.io.*;
import java.awt.FlowLayout;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.io.File;
import javax.swing.JButton;
import javax.swing.JFileChooser;
import javax.swing.JFrame;
import javax.swing.JLabel;

public class Server
{
    private ServerSocket serverSocket;
    private Socket socketOut;
    private FileChoose f;
    private FileInputStream fis = null;
    private BufferedOutputStream bis = null;
    private OutputStream os = null;

    public Server(int port)
    {
        try
        {
            serverSocket = new ServerSocket(4444);
        }
        catch (IOException e)
        {
            System.err.println("Could not listen on port: 4444.");
            System.exit(-1);
        }

        try
        {
            socketOut = serverSocket.accept();
        }
        catch (IOException e)
        {}

        f = new FileChoose();

    }

    public static void main(String[] args)
    {
        Server s = new Server(4444);
    }

    private class FileChoose extends JFrame
    {
        private JButton openButton, openButton1, openButton2;
        private String filelist = "";
        private FileInputStream fis;
        private PrintWriter writer = null;
        private BufferedInputStream bis = null;

        public FileChoose()
        {
            super("File Chooser Test Frame");

            setLayout(new FlowLayout());
            openButton = new JButton("Open");
            openButton1 = new JButton("Send");
            openButton2 = new JButton("Done");

            openButton.addActionListener(
                new ActionListener()
                {
                    public void actionPerformed(ActionEvent ae)
                    {

                        JFileChooser chooser = new JFileChooser();
                        int option = chooser.showOpenDialog(FileChoose.this);
                        if (option == JFileChooser.APPROVE_OPTION)
                        {
                            File sf = chooser.getSelectedFile();
                            filelist = sf.getPath();
                            System.out.println (filelist);
                        }
                    }
                }
            );

            openButton1.addActionListener(
                new ActionListener()
                {
                    public void actionPerformed(ActionEvent ae)
                    {
                        sendFile();

                    }
                }
            );
            openButton2.addActionListener(
                new ActionListener()
                {
                    public void actionPerformed(ActionEvent ae)
                    {
                        closeSockets();
                    }
                }
            );


            add(openButton);
            add(openButton1);
            add(openButton2);

            setSize(350, 200);
            setVisible(true);
        }

        public void sendFile()
        {
            try
            {
                File file = new File (filelist);
                byte[] buffer = new byte[(int) file.length()];
                fis = new FileInputStream(file);
                bis = new BufferedInputStream (fis);
                bis.read(buffer, 0, buffer.length);
                os = socketOut.getOutputStream();
                System.out.println ("Sending " + filelist  + " Bytes = " + buffer.length);
                writer = new PrintWriter(os, true);
                writer.println (String.valueOf(buffer.length));
                System.out.println ("Sending " +buffer.length);
                os.write(buffer, 0, buffer.length);
                os.flush();
                System.out.println ("Done sending");

            }
            catch(FileNotFoundException e)
            {}
            catch(IOException e)
            {}
        }

        public void closeSockets()
        {
            try
            {
                bis.close();
                os.close();
                socketOut.close();
                serverSocket.close();
            }
            catch(IOException e)
            {}
        }
    }

}

import java.net.*;
import java.io.*;
import java.awt.image.*;
import java.awt.*;
import javax.swing.*;
import javax.imageio.*;
import java.util.Scanner;

public class Client
{
    private static Socket socket  = null;
    private static FileOutputStream fos = null;
    private static BufferedOutputStream bos = null;
    private static int count1 = 0, line = 0, sum = 0;
    private static String num = "";
    private static BufferedReader reader = null;

    public static void main (String args[]) throws IOException 
    {
        try
        {
            socket = new Socket("localhost", 4444);
        } 
        catch (UnknownHostException e) {
            System.err.println("Don't know about host: localhost");
            System.exit(1);
        }
        InputStream is = socket.getInputStream();
        byte[] buffer = new byte[4096];
        fos = new FileOutputStream("image" + count1+ ".jpg");
        reader = new BufferedReader (new InputStreamReader(is));
        bos = new BufferedOutputStream(fos);

        int count = 0; 
        System.out.println ("file about to be read" );

        boolean flag = true;
        while (flag)
        {
            line++;
            if (line == 1)
            {
                num = reader.readLine();
                System.out.println ("Bytes Total = " + num);
            }
            else
            {
                count = is.read(buffer, 0, buffer.length);
                sum += count;
                System.out.println ("Number of Bytes Read so Far =" + sum);

                if (count == -1)
                {
                    flag = false;
                    System.out.println ("End of Program");
                }
                else 
                {
                    if (sum < Integer.parseInt(num))
                    {
                        bos.write(buffer, 0, count);
                    }
                    else
                    {
                        bos.write(buffer, 0, count);
                        System.out.println ("Writing to Buffer");
                        System.out.println ("file received");
                        displayPic();
                        count1++;
                        for (int i = 0; i <4096; i++)
                        {
                            buffer[i] = 0;
                        }

                        fos = new FileOutputStream("image" + count1 +".jpg");
                        bos = new BufferedOutputStream(fos);
                        sum = 0;
                        line = 0;

                    }
                }
            }
        }
        fos.close();
        bos.close();
        socket.close();

    }

    public static void displayPic()
    {
        JFrame frame = new JFrame();
        JLabel label = new JLabel(new ImageIcon("image" + count1 +".jpg"));
        frame.getContentPane().add(label, BorderLayout.CENTER);
        frame.setSize(800, 800);
        frame.setVisible(true);
    }

}

I'm very suspicious about mixing printwriter and direct calls on an OutputStream. Try getting rid of the printwriter stuff and simply write the int file length as an int.

Hello,

I tried the following:

On the Server side, removed PrintWriter and used the write(int) to send the number of bytes:

public void sendFile()
        {
            try
            {
                File file = new File (filelist);
                byte[] buffer = new byte[(int) file.length()];
                fis = new FileInputStream(file);
                bis = new BufferedInputStream (fis);
                bis.read(buffer, 0, buffer.length);
                os = socketOut.getOutputStream();
                System.out.println ("Sending " + filelist  + " Bytes = " + buffer.length);
                //                 writer = new PrintWriter(os, true);
                //                 writer.println (buffer.length);
                os.write(buffer.length);
                System.out.println ("Sending " +buffer.length);
                os.write(buffer, 0, buffer.length);
                os.flush();
                System.out.println ("Done sending");

            }
            catch(FileNotFoundException e)
            {}
            catch(IOException e)
            {}
        }

On the Client side, the code remained the same, but I used the Inputstreamreader.read() instead of BufferedReader.readLine():

while (flag)
        {
            line++;
            System.out.println ("Line Number = " + line);
            if (line == 1)
            {
                num = is.read();
                System.out.println ("Bytes Total = " + num);

            }
            else
            {
                count = is.read(buffer, 0, buffer.length);
                sum += count;
                System.out.println ("Number of Bytes Read so Far =" + sum);

                if (count == -1)
                {
                    flag = false;
                    System.out.println ("End of Program");
                }
                else 
                {
                    if (sum < num)
                    {
                        bos.write(buffer, 0, count);
                    }
                    else
                    {
                        System.out.println ("Writing to Buffer");
                        System.out.println ("file received");
                        displayPic();
                        count1++;
                        for (int i = 0; i <4096; i++)
                        {
                            buffer[i] = 0;
                        }

                        fos = new FileOutputStream("image" + count1 +".jpg");
                        bos = new BufferedOutputStream(fos);
                        sum = 0;
                        line = 0;

                    }
                }
            }
        }
        fos.close();
        bos.close();
        socket.close();

    }

The issue I am having is: The server's console has the following output, which makes sense:

Sending C:\Users\Me\Desktop\pic.jpg Bytes = 57991
Sending 57991
Done sending

But the Client does not receive the proper value for the total number of bytes that the server sends:

file about to be read
Line Number = 1
Bytes Total = 135

That is where all my issues are. Once this is fixed, everything else should work.

Thanks in advance again for your help!

write(int) is misleading - it takes an int but just writes the last 8 bits of that as a single byte. So your length gets truncated to 8 bits. Still - it's better than mixing stream types!
Why not go up 1 level to DataOutputStream/InputStream so you can use writeInt and readInt (as well as your existing byte array writes & reads)

James,

I tried the DataInputStream/DataOutputStream objects and I find the following:

a) Once a file is selected, the terminal output on the Server for the bytes sent and on the Client side for bytes received and processed in chunks of buffer size are accurate.

b) The image transferred is still either partially missing some portions (bottom parts) or if the image size is less than 4096 bytes (my buffer size), I see nothing. Thank you for your answers and if you can see something obviously wrong in my approach, let me know. Nothing in my program has changed besides the DataInputStream/DataOutputStream objects as suggested by you.

Thank you!

Edited 2 Years Ago by sciprog22

I just spotted this, maybe it's your bug?
Line 24 - if sum == num your if test fails and you don't process the data - so that looks like you are ignoring the last block of each file (for the last block the total number of bytes read should == num, not < num)

Hello,

Certainly a bug, which I just fixed and the picture is better but it's still missing certain parts of the bottom. I cannot see what else in while loop below that I am doing wrong. Everything else prints out accurately on the terminal ever since I changed it to DataInputStream/DataOutputStream as per your suggestion:

 while (flag)
        {
            line++;
            System.out.println ("Line Number = " + line);
            if (line == 1)
            {
                num = is.readInt();
                System.out.println ("Bytes Total = " + num);
                System.out.println ("Line Number = " + line);
            }
            else
            {
                count = is.read(buffer, 0, buffer.length);
                sum += count;
                System.out.println ("Number of Bytes Read so Far =" + sum);

                if (count == -1)
                {
                    flag = false;
                    System.out.println ("End of Program");
                }
                else 
                {
                    if (sum < num)
                    {
                        bos.write(buffer, 0, count);
                    }
                    else
                    {
                        bos.write(buffer, 0, count);
                        System.out.println ("Writing to Buffer");
                        System.out.println ("file received");
                        displayPic();
                        count1++;
                        for (int i = 0; i <4096; i++)
                        {
                            buffer[i] = 0;
                        }

                        fos = new FileOutputStream("image" + count1 +".jpg");
                        bos = new BufferedOutputStream(fos);
                        sum = 0;
                        line = 0;

                    }
                }
            }
        }

That's a bit confusing...
The logic will be simpler and safer (and without repetitions) if you structure it as:

count = is.read(...
if count >= 0
    bos.write(buffer, 0, count);
else
    // end of file reached
    displayPic();

(plus the diagnostic prints etc).

If I am not mistaken, is.read(byte[], int, int) returns -1 only when the socket/streams in the Server are closed. I don't want that. I want as many files to be sent by the server as chosen and at the very end of all that, close the socket on the server side, which will also end the while loop on the client side.That's why I wrote the program as above.

Edited 2 Years Ago by sciprog22

OK, that makes sense. You're right.
In that case... maybe some kind of buffer flushing issue? I see you flush() the stream, so it should be OK, but anyway...
Just for a test, try writing/reading another int (eg -1) immediately after the file so you can confirm that nothing is still left in a network buffer somewhere.
Maybo someone else has some ideas here... please?

Hello James,

Firstly, thank you so much for your helpful suggestions. It made my program a lot better. I tried the "-1", but the Client is not receiving it. It just waits on the next input from Server without reading the (-1).

Following is the code I changed in Server:

      os.writeInt(buffer.length);
      System.out.println ("Sending " +buffer.length);
      os.write(buffer, 0, buffer.length);
      os.writeInt(-1);
      System.out.println ("Sending -1");
      os.flush();
      System.out.println ("Done sending");

I hardcoded my Client just for a single image to check if it receives -1:

  while (flag)
            {
                line++;
                System.out.println ("Line Number = " + line);
                if (line == 1  || line == 17)
                {
                    num = is.readInt();
                    if ( line == 1)
                    {
                        System.out.println ("Bytes Total = " + num);
                        System.out.println ("Line Number = " + line);
                    }
                    else
                    {
                        System.out.println ("Received = " + num);
                    }

                }
                else
                {
                    count = is.read(buffer, 0, buffer.length);
                    sum += count;
                    System.out.println ("Number of Bytes Read so Far =" + sum);

                    if (count == -1)
                    {
                        System.out.println ("Received -1");
                        flag = false;
                        System.out.println ("End of Program");
                    }
                    else 
                    {
                        if (sum < num)
                        {
                            bos.write(buffer, 0, count);
                        }
                        else
                        {
                            bos.write(buffer, 0, count);
                            System.out.println ("Writing to Buffer");
                            System.out.println ("file received");
                            displayPic();
                            count1++;
                            for (int i = 0; i <4096; i++)
                            {
                                buffer[i] = 0;
                            }

                            fos = new FileOutputStream("image" + count1 +".jpg");
                            bos = new BufferedOutputStream(fos);
                            //sum = 0;
                            //line = 0;

                        }
                    }
                }
            }

The Server Console Output:

 C:\Users\Me\Desktop\pic.jpg

    Sending C:\Users\Me\Desktop\pic.jpg Bytes = 57991
    Sending 57991
    Sending -1
    Done sending

The Client Console Output:

  file about to be read
    Line Number = 1
    Bytes Total = 57991
    Line Number = 1
    Line Number = 2
    Number of Bytes Read so Far =4096
    Line Number = 3
    Number of Bytes Read so Far =8192
    Line Number = 4
    Number of Bytes Read so Far =12288
    Line Number = 5
    Number of Bytes Read so Far =16384
    Line Number = 6
    Number of Bytes Read so Far =20480
    Line Number = 7
    Number of Bytes Read so Far =24576
    Line Number = 8
    Number of Bytes Read so Far =28672
    Line Number = 9
    Number of Bytes Read so Far =32768
    Line Number = 10
    Number of Bytes Read so Far =36864
    Line Number = 11
    Number of Bytes Read so Far =40960
    Line Number = 12
    Number of Bytes Read so Far =45056
    Line Number = 13
    Number of Bytes Read so Far =49152
    Line Number = 14
    Number of Bytes Read so Far =53248
    Line Number = 15
    Number of Bytes Read so Far =57344
    Line Number = 16
    Number of Bytes Read so Far =57995
    Writing to Buffer
    file received
    Line Number = 17

The Client reads four more bytes than what the server sent only if I add the -1. Not sure why the line in Client, " if (line == 1 || line == 17)" is not true for line #17 and the "-1" is not seen in the input stream.

Thank you again!

Those 4 bytes are the extra int -1.

I think you need some way to limit yout read loop to just read the right number of bytes from the input stream (ie the total bytes value that you read at the beginning) to create the image. Eg create a byte array of the right size (like you do in the server) and read into that in one go.
(I'm having to make this up as I go along because personally I've never done it this way, I have always used ObjectOutputStream/ObjectInputStream or XML to send stuff like this over a Socket.)

James,

THAT DID IT! It works great now. Thank you so much for your patience and help!

Regards

This question has already been answered. Start a new discussion instead.