1

I'm writing simple client - server application. Everything is ok but when i change InputStream and OutputStream to ObjectOutputStream and ObjectInputStream my application doesn't send the messages. Can anyone help me and show me the problem ?

Here is the Serwer.java:

class InWorke implements Runnable{

    BufferedReader odczyt=null;
    String slowo;
    ObjectInputStream ois=null;
    Message message;

    InWorke(ObjectInputStream ois) {
        this.ois=ois;
    }

    public void run() {
        while(true) {
            try {
                slowo = (String) ois.readObject();
            } catch (ClassNotFoundException e) {
                // TODO Auto-generated catch block
                e.printStackTrace();
            } catch (IOException e) {
                // TODO Auto-generated catch block
                e.printStackTrace();
            }
            System.out.println(slowo);
            Thread.yield();
        }               }

}

class OutWorke implements Runnable{
    Socket socket=null;
    BufferedReader odczytWe=null;
    DataOutputStream zapis=null;
    String slowo=null;
    Message message; // it is the simple class to serialization
    ObjectOutputStream oos;

    OutWorke(Socket socket,ObjectOutputStream oos) {
        this.socket=socket;
        this.oos=oos;
    }

    public void run() {
        while(true) {
            odczytWe=new BufferedReader(new InputStreamReader(System.in));
            try {
                slowo=odczytWe.readLine();
            } catch (IOException e) {
                // TODO Auto-generated catch block
                e.printStackTrace();
            }
            try {
                    oos.writeObject(slowo);
                    oos.flush();
                } catch (IOException e1) {
                    // TODO Auto-generated catch block
                    e1.printStackTrace();
                }
            Thread.yield();

    }

}
}

public class Klient {
    public static void main(String[] args) {

    Socket socket=null;
    ExecutorService exec=Executors.newCachedThreadPool();

    ObjectOutputStream oos=null;
    ObjectInputStream ois=null;

    try {
        socket=new Socket("localhost", 8881);
    } catch (UnknownHostException e) {
        // TODO Auto-generated catch block
        e.printStackTrace();
    } catch (IOException e) {
        // TODO Auto-generated catch block
        e.printStackTrace();
    }
    try {
        //we=socket.getInputStream();
        ois=new ObjectInputStream(socket.getInputStream());
    } catch (IOException e) {
        // TODO Auto-generated catch block
        e.printStackTrace();
    }
    try {
        //wy=socket.getOutputStream();
        oos=new ObjectOutputStream(socket.getOutputStream());
    } catch (IOException e) {
        // TODO Auto-generated catch block
        e.printStackTrace();
    }

    exec.execute(new OutWorke(socket, oos));
    exec.execute(new InWorke(ois));

 }
} 

Klient.java:

class InWorker implements Runnable{

    Socket socket=null;
    //InputStream we=null;
    //OutputStream wy=null;
    String slowo=null;
    BufferedReader odczyt=null;
    ObjectOutputStream oos;
    ObjectInputStream ois;
    Message message=null;

    InWorker(Socket socket,ObjectInputStream ois) {
        this.socket=socket;
        this.ois=ois;
    }

    public void run() {
                while(true) {
                try {
                    slowo=(String) ois.readObject();
                } catch (ClassNotFoundException e) {
                    // TODO Auto-generated catch block
                    e.printStackTrace();
                } catch (IOException e) {
                    // TODO Auto-generated catch block
                    e.printStackTrace();
                }
                System.out.println(slowo);
                Thread.yield();
            }

            }
}

class OutWorker implements Runnable{

    DataOutputStream zapis=null;
    BufferedReader odczyt=null;
    //OutputStream wy=null;
    String tekst=null;
    ObjectOutputStream oos=null;
    Message message;

    OutWorker(ObjectOutputStream oos) {
        this.oos=oos;
    }

    public void run() {
        while(true) {
        odczyt=new BufferedReader(new InputStreamReader(System.in));
        try {
            tekst=odczyt.readLine();
        } catch (IOException e1) {
            // TODO Auto-generated catch block
            e1.printStackTrace();
        }
        try {
            oos.writeObject(tekst);
            oos.flush();
        } catch (IOException e1) {
            // TODO Auto-generated catch block
            e1.printStackTrace();
        }
        Thread.yield();
        }
    }

}

public class Serwer {

    public static void main(String[] args) {
        ServerSocket serversocket=null;
        Socket socket=null;
        //InputStream we=null;
        //OutputStream wy=null;
        ObjectOutputStream oos=null;
        ObjectInputStream ois=null;

        ExecutorService exec=Executors.newCachedThreadPool();

        try {
            serversocket=new ServerSocket(8881);
        } catch (IOException e) {
            // TODO Auto-generated catch block
            e.printStackTrace();
        }
        try {
            socket=serversocket.accept();
        } catch (IOException e) {
            // TODO Auto-generated catch block
            e.printStackTrace();
        }
        try {
            ois=new ObjectInputStream(socket.getInputStream());
        } catch (IOException e) {
            // TODO Auto-generated catch block
            e.printStackTrace();
        }
        try {
            oos=new ObjectOutputStream(socket.getOutputStream());
        } catch (IOException e) {
            // TODO Auto-generated catch block
            e.printStackTrace();
        }
        exec.execute(new InWorker(socket, ois));
        exec.execute(new OutWorker(oos));

    }

}
user1518451
  • 1,373
  • 4
  • 20
  • 25

2 Answers2

4

Check constructor of ObjectInputStream: constructor.
It says:

This constructor will block until the corresponding ObjectOutputStream has written and flushed the header.

So you need to create and flush corresponding ObjectOutputStream. Now you are creating ObjectInputStreams before output stream for both server and client. They block programs because no output stream is created. You should create output streams first, call flush on them and only then create input streams.

Mikita Belahlazau
  • 14,587
  • 1
  • 35
  • 42
  • AFAIK there is no need to call `flush()`, the implementation does that itself – Mark Rotteveel Jan 08 '13 at 15:09
  • it works without `flush()`, but documentation for constructor of `ObjectOutputStream` says: "...callers may wish to flush the stream immediately to ensure that constructors for receiving ObjectInputStreams will not block..." – user85421 Jan 08 '13 at 15:15
  • I change order (in server and client): `try { oos=new ObjectOutputStream(socket.getOutputStream()); oos.flush(); } catch (IOException e) { // TODO Auto-generated catch block e.printStackTrace(); } try { ois=new ObjectInputStream(socket.getInputStream()); } catch (IOException e) { // TODO Auto-generated catch block e.printStackTrace(); } ` but program still doesn't work. – user1518451 Jan 08 '13 at 15:24
  • 1
    @user1518451 It works for me: https://gist.github.com/7802c07588beb198b7fd Only client sends "Hello, world." instead of reading from console. – Mikita Belahlazau Jan 08 '13 at 15:35
1

The root issue is just as Nikita points out. The implementation solution is to have the server and client get the input and output streams in the opposite order. If one is getting the inputstream first have the other get the outputstream, etc. I switched the client to get the outputstream first and it all works. I then put it back and change the Server and it all works that way to... you can choose which to change.

For Reference: http://docs.oracle.com/javase/6/docs/api/index.html?java/io/ObjectOutputStream.html

jco.owens
  • 525
  • 2
  • 5