0

I'm doing a simple echo chat and server, but methods send and receive in class Connection don't work with ObjectInputStream and ObjectOutputStream, but with PrintWriter and BufferedReader work fine.

Now I'm trying to understand the serialization using sockets, help me to understand why this code does not work:

Client

public class Client {
    private Connection connection;

    private String getServerAddress() {
        return "localhost";
    }

    private int getServerPort() {
        return 4444;
    }

    public void run() {
        BufferedReader bis = new BufferedReader(new InputStreamReader(System.in));

        try {
            connection = new Connection(new Socket(getServerAddress(), getServerPort()));

            SocketThread socketThread = new SocketThread();
            socketThread.setDaemon(true);
            socketThread.start();

            while (true) {
                String text = bis.readLine();
                if (text.equalsIgnoreCase("exit"))
                    break;
                connection.send(text);
            }
        } catch (Exception e) {
            e.printStackTrace();
        }
    }

    public static void main(String[] args) {
        Client client = new Client();
        client.run();
    }

    public class SocketThread extends Thread {
        @Override
        public void run() {
            try {
                while (true) {
                    String message = connection.receive();
                    System.out.println(message);
                }

            } catch (Exception e) {
                e.printStackTrace();
            }
        }
    }
}

Connection

public class Connection implements Closeable {
    private final Socket socket;
    private final ObjectInputStream in;
    private final ObjectOutputStream out;

    public Connection(Socket socket) throws Exception {
        this.socket = socket;
        this.in = new ObjectInputStream(socket.getInputStream());
        this.out = new ObjectOutputStream(socket.getOutputStream());
    }

    public void send(String message) throws Exception {
        out.writeObject(message);
    }

    public String receive() throws Exception {
        return (String) in.readObject();
    }

    @Override
    public void close() throws IOException {
        in.close();
        out.close();
        socket.close();
    }
}

Server

public class Server {

    public static void main(String[] args) {
        int port = 4444;

        try (ServerSocket serverSocket = new ServerSocket(port)) {
            while (true) {
                Socket socket = serverSocket.accept();
                new Handler(socket).start();
            }
        } catch (Exception e) {
            e.printStackTrace();
        }
    }

    private static class Handler extends Thread {
        private Socket socket;

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

        @Override
        public void run() {
            try (Connection connection = new Connection(socket)) {
                while (true) {
                    String message = connection.receive();

                    if (message.equals("exit"))
                        break;

                    System.out.println(message);

                    connection.send("Echo: " + message);
                }
            } catch (Exception e) {
            }
        }
    }
}
António Ribeiro
  • 4,129
  • 5
  • 32
  • 49
Evgeniy
  • 23
  • 1
  • 3
  • 3
    Please post what ever you tried and the error message you got. – Yohannes Gebremariam Feb 17 '16 at 21:50
  • I do not get an error message. I'm trying using synchronized block's in methods "send" and "receive" for ObjectInputStream and ObjectOutputStream, but the server does not return the echo message back to the client. But with PrintWritter and BufferedReader it's working. – Evgeniy Feb 17 '16 at 21:58
  • Try to change order of `this.in = new ObjectInputStream(socket.getInputStream()); this.out = new ObjectOutputStream(socket.getOutputStream());` in your `Connection`. Also you may want to `out.flush()` each time you are sending something (I am not sure if it is flushed automatically which may cause waiting until used buffer will be full). – Pshemo Feb 17 '16 at 23:19
  • Thank you! Now everything is working. – Evgeniy Feb 17 '16 at 23:50

1 Answers1

0

This is because ObjectInputStream blocks trying to read the stream header written by an ObjectOutputStream in its constructor, and you are creating both of your input streams before the output streams. You can solve this by switching the order that you create the object streams in:

    this.out = new ObjectOutputStream(socket.getOutputStream());
    this.in = new ObjectInputStream(socket.getInputStream());

The javadoc for the ObjectOutputStream constructor also notes that you might want to flush the stream after creating it to ensure the header is sent.

Alex - GlassEditor.com
  • 14,957
  • 5
  • 49
  • 49