0

So I have seen a lot of different questions like this but no definitive help, at least to my understanding or my personal application. I am making a socket "chat room" program that allows the user to send images to selected users through a central server. I can establish the clients to connect but when sending an image this error occurs. Here is my code:

Client:

    Thread thread = new Thread() {
        @Override
        public void run() {
            try {
                s = new Socket("localhost", 4000);

                while (s.isConnected()) {
                    oos = new ObjectOutputStream(s.getOutputStream());
                    if (!initialized) {
                        oos.writeObject(identity);
                        oos.flush();
                        oos.reset();
                        initialized = true;
                    }
                    baos = new ByteArrayOutputStream(1000);
                    // Take screenshot
                    BufferedImage img = new Robot()
                            .createScreenCapture(new Rectangle(Toolkit.getDefaultToolkit().getScreenSize()));

                    // Write img to baos 
                    ImageIO.write(img, "jpg", baos);

                    // Send image over socket
                    oos.writeObject(baos.toByteArray());
                    oos.flush();
                    oos.reset();
                }
            } catch (Exception e) {
                e.printStackTrace();
            }

        }
    };
    thread.start();

Central Server Home:

    public Home() {
    initComponents();
    textView = new Terminal(terminal);

    users = new CopyOnWriteArrayList<>();

    Thread startServer = new Thread(new ServerStart());
    startServer.start();
}

public class ServerStart implements Runnable {

    @Override
    public void run() {

        try {
            serverSock = new ServerSocket(4000);

            terminal.append("Server started...\n");

            while (true) {
                // Detect client connection
                Socket clientSock = serverSock.accept();

                Thread thread = new Thread(new ClientHandler(clientSock));
                thread.start();
            }
        } catch (Exception ex) {
            ex.printStackTrace();
        }
    }
}

public class ClientHandler implements Runnable {

    Socket socket;

    public ClientHandler(Socket socket) {
        this.socket = socket;
    }

    @Override
    public void run() {
        try {
                User user = new User(socket);
                terminal.append(user.getName() + " connected as " + user.getType() + "...\n");
                if (user.getType().equals(User.TYPE_01)) {
                    users.add(user);
                } else {
                    User client = findUser(user);
                    while(true){
                        user.sendScreen(client.receiveScreen());
                    }
                }
        } catch (Exception e) {
            e.printStackTrace();
        }
    }

    private User findUser(User user) {
        for (User client : users) {
            if (client.getCompany().equals(user.getCompany())) {
                if (client.getName().equals(user.getName())) {
                    return client;
                }
            }
        }
        return null;
    }
}

Central Server User:

    public static final String TYPE_00 = "VIEWER";
public static final String TYPE_01 = "CLIENT";

private byte[] bytes;
private ObjectInputStream in;
private ObjectOutputStream out;
private String company, name, type;

public User(Socket socket) throws IOException {
    this.out = new ObjectOutputStream(socket.getOutputStream());
    this.in = new ObjectInputStream(socket.getInputStream());
    setUserType();
}

public void sendScreen(byte[] bytes) {
    try {
        out.writeObject(bytes);
        out.flush();
    } catch (Exception ex) {
        ex.printStackTrace();
    }
}

public byte[] receiveScreen() {
    byte[] bytes = null;
    try {
        bytes = (byte[]) in.readObject();
    } catch (Exception e) {
        e.printStackTrace();
    }
    return bytes;
}

public String getCompany() {
    return company;
}

public String getName() {
    return name;
}

public String getType() {
    return type;
}

public void setUserType()
{
    String[] strings = null;
    try{
        strings = (String[])in.readObject();
        type = strings[0];
        company = strings[1];
        name = strings[2];
    } catch(Exception e){
        e.printStackTrace();
    }
}

Client Viewer:

    Thread thread = new Thread() {
        @Override
        public void run() {
            try {
                Socket s = new Socket("localhost",4000);


                String[] strings = { TYPE, "Vision", "cadams" };


                while (s.isConnected()) {

                    if(!initialized){
                        System.out.println("initialized");
                        oos = new ObjectOutputStream(s.getOutputStream());
                        oos.writeObject(strings);
                        oos.flush();
                        oos.reset();
                        initialized = true;
                    }
                    ois = new ObjectInputStream(s.getInputStream());

                    byte[] bytes = (byte[]) ois.readObject();
                    BufferedImage img = ImageIO.read(new ByteArrayInputStream(bytes));
                    ImageIcon ico = new ImageIcon(
                            img.getScaledInstance(viewer.getWidth(), viewer.getHeight(), Image.SCALE_SMOOTH));
                    viewer.setIcon(ico);
                }
            } catch (Exception e) {
                e.printStackTrace();
            }
        }
    };
    thread.start();

}

I have done some extensive research and know that this could be from my streams looking like a bowl of ramen noodles but I haven't seen any sort of proposal on how to fix it in terms of source. I thank those who can contribute and please let me know if there is anything I can do to further understanding.

  • That's far too much code. It is up to you to post a *short* code snippet that demonstrates your problem. Probably one piece of code that write something to a stream and one piece that reads it, and causes the error. – Erwin Bolwidt Sep 30 '15 at 05:34
  • Using `ObjectStreams` is a very very very bad idea when you're not familiar with streams and don't understand what magic they do. – Kayaman Sep 30 '15 at 05:38
  • Have a look at this question is SE: http://stackoverflow.com/questions/25086868/how-to-send-images-through-sockets-in-java – Ravindra babu Sep 30 '15 at 05:40
  • _The error you get is because the objectOutputStream writes a header, which is expected by objectIutputStream. As you are not writing multiple streams, but simply multiple objects, then the next objectInputStream created on the socket input fails to find a second header, and throws an exception._. Check similar problem and answer [here](http://stackoverflow.com/a/2939113/434408) – a3.14_Infinity Sep 30 '15 at 05:40

1 Answers1

0

Don't keep creating new ObjectInput/OutputStreams. Use the same ones for the life of the socket.

NB while (s.isConnected() isn't valid. It doesn't magically become false when the peer disconnects. You need to handle end of stream and the various socket termination exceptions.

user207421
  • 305,947
  • 44
  • 307
  • 483