I am having trouble bouncing object between the client and the server.
Create an object. Update some fields. Send to Server. (this part works)
SomeObject thisObject = new SomeObject();
thisObject.setSomeValue(13); // update object to be sent
PrintStream toServer = new PrintStream(sock.getOutputStream());
ObjectOutputStream oos = new ObjectOutputStream(toServer);
oos.writeObject(thisObject);
oos.close();
toServer.println(oos); // send object to server
toServer.flush();
Right after this, server further updates some value and sets it to 1919;
ObjectInputStream objFromClient = new ObjectInputStream(new BufferedInputStream(
sock.getInputStream()));
Served thisObject = (Served) objFromClient.readObject();
thisObject.setSomeValue(1919);
Server then sends the object back to client
toClient = new PrintStream(sock.getOutputStream());
ObjectOutputStream oos = new ObjectOutputStream(toClient);
oos.writeObject(thisObject);
oos.close();
objFromClient.close();
sock.close();
But when the time comes to pick up the object back on the client side .. programs fails with Socket Closed exception
ObjectInputStream objFromServer = new ObjectInputStream(
new BufferedInputStream(sock.getInputStream())); //java.net.SocketException: Socket is closed
thisObject = (Served) objFromServer.readObject();
....
Please help me understand the issue
My guess is you're using the same Socket to both send and receive from the client. When you close the ObjectOutputStream on the client, this closes the underlying OutputStream, which closes sock. Then, when you try to reuse it below, it's been closed and throws an exception.
Instead, wait for the transaction to finish before closing your resources in the client code (which should be done in a finally block by the way). Or, if waiting is problematic, use a new Socket instead.
Related
I have the following code that works (please assume that hostname and port are initialized to their proper values, and that Message is a serializable class):
//Example 1 - everything works as expected
Message message = new Message();
try(Socket serverSocket = new Socket(hostname, port))
{
ObjectOutputStream outStream = new ObjectOutputStream(serverSocket.getOutputStream());
outStream.writeObject(message);
outStream.flush();
ObjectInputStream inStream = new ObjectInputStream(serverSocket.getInputStream());
Object response = inStream.readObject();
}
When I move the instantiation of the ObjectInputStream to occur immediately after the ObjectOutputStream instantiation, execution of my application hangs indefinitely:
//Example 2 - client locks up
Message message = new Message();
try(Socket serverSocket = new Socket(hostname, port))
{
ObjectOutputStream outStream = new ObjectOutputStream(serverSocket.getOutputStream());
ObjectInputStream inStream = new ObjectInputStream(serverSocket.getInputStream());
outStream.writeObject(message);
outStream.flush();
Object response = inStream.readObject();
}
I'm looking for a good explanation as to why the second example locks up consistently, and the first example seems to work without a hitch. Strangely, if I use a debugger (Eclipse debugger) on the client and server with this second example, I'm seeing the message make it through to the server, so the writeObject() call is being executed. However, in the client, the debugger gets stuck on the constructor for the ObjectInputStream.
If we go and have a read of the API docs for the ObjectInputStream constructor
The important part:
This constructor will block until the corresponding ObjectOutputStream
has written and flushed the header.
Constructing an ObjectOutputStream writes a header to the stream. Constructing an ObjectInputStream reads it. If both ends construct the ObjectInputStream first, you will therefore get a deadlock.
Solution: construct the ObjectOutputStream first, at both ends, to make sure it can't happen.
Based on the following information from my prof:
The client creates ObjectOutputStream and ObjectInputStream objects to send the request, and to receive the reply. The CalculateClient constructor is:
public CalculateClient( String host, int port )
throws IOException
{
/* determine the address of the server and connect to it */
serverHost = InetAddress.getByName( host );
serverPort = port;
calculate = new Socket( serverHost, serverPort );
OutputStream out = calculate.getOutputStream();
request = new ObjectOutputStream(
new BufferedOutputStream( out ));
request.flush();
// ObjectInputStream blocks until
// the connected side flushes its ObjectOutputStream
InputStream in = calculate.getInputStream();
reply = new ObjectInputStream( in );
}
In network applications, the construction order of the input and output socket streams when using object streams is important. The ObjectOutputStream must be created first. It then should be flushed. The ObjectInputStream can then be created.
He doesn't elaborate as to why. Why is this true?
It is explained in the comments of the code you posted, isn't it?
// ObjectInputStream blocks until
// the connected side flushes its ObjectOutputStream
So if you try to create the ObjectInputStream the constructor waits until the corresponding ObjectOutputStream's flush() method is called. Since you haven't created it yet, guess what happens?
As an alternative to asking this question, you could have simply switched the creation order and observed the results. It takes arguably less effort on your part and as a bonus you've learned how to problem-solve and think critically.
I have a client class and a server class. There is a client method which I use to call the server and my code hangs if I try use this method more than once during a jvm session.
Client code's main method:
methodA();
methodA();
ois.close(); //ObjectInputStream
oos.close(); //ObjrctOutputStream
is.close(); //InputStream
os.close(); //OutputStream
socket.close();
Client code's methodA() looks like this:
os = socket.getOutputStream();
oos = new ObjectOutputStream(os);
oos.writeObject(obj);
is = socket.getInputStream();
ois = new ObjectInputStream(is);
Object o = ois.readObject();
Server code's main method looks like:
while (true) {
Socket socket = serverSocket.accept();
is = socket.getInputStream();
ois = new ObjectInputStream(is);
Object o = ois.readObject();
servermethod();
}
oos.close();
ois.close();
is.close();
os.close();
serverSocket.close();
The server's serverMethod() looks like:
os = socket.getOutputStream();
oos = new ObjectOutputStream(os);
Object ob = getObject() ; //this method is working fine
oos.writeObject(ob);
What I wanted to do was to have the client call the server a few times using methodA(). I might not be handling the streams correctly. Any help?
There are definitely a few things wrong with this code:
You are creating ObjectInputStream and ObjectOutputStream repeatedly on top of the same streams. This is not how how they are supposed to be used. What you are supposed to do is create the ObjectXxxStream once, and then call readObject or writeObject multiple times on the same ObjectXxxStream. If you are sending the same object multiple times, you need to call reset before writing the object again.
You are not flushing the streams. If you don't flush after writing, there is no guarantee that the serialized representation will get sent to the other end ... where something is waiting for the bytes to arrive.
Your server end code is written in a way to read only one object and write only one object to a newly created Socket. Hence you try to reuse the Socket a second or nth time, it doesn't get back a response from the server. There are 2 ways to fix it.
You can fix on the server end : This will be an elaborate change, but better use of resources. You don't stop reading the stream until it is closed.
You fix it in the client end : Instead of creating the Socket outside the main method, you create the Socket inside MethodA(). Easy and dirty solution though.
For some reasons i have to set up on android SocketServer which waits for connection with computer. All is going good, socket with client (computer) is creating, but streams don't open. It's just pausing without any error or message.
client:
s = new Socket(ip, 4567);
ois = new ObjectInputStream(s.getInputStream());
System.out.println("ois..");// not showing, so can't open input stream
oos = new ObjectOutputStream(s.getOutputStream());
System.out.println("oos.."); // same here
server:
socket = new ServerSocket(4567);
System.out.println("Waiting for connection,,"); // showing
client = socket.accept();
System.out.println("Connected"); //showing
ois = new ObjectInputStream(client.getInputStream());
System.out.println("ois.."); // not showing
oos = new ObjectOutputStream(client.getOutputStream());
System.out.println("oos.."); // not showing too
System.out.println("Stream,s opened");
My apk has INTERNET premissions. I'm using 4567 port. Any other application doesn't block the port.
What can be wrong?
Try opening the ObjectOutputStream first in your server.
socket = new ServerSocket(4567);
System.out.println("Waiting for connection,,"); // showing
client = socket.accept();
System.out.println("Connected"); //showing
oos = new ObjectOutputStream(client.getOutputStream());
ois = new ObjectInputStream(client.getInputStream());
System.out.println("Stream,s opened");
I don't see any timeouts in there, which is why it just stops.
There's probably some network problem; have you verified the IP address of the device is correct?
It's unlikely, but there could be some firewall rule blocking the connection.
This is the code that i used on client socket
Socket connected = Server.accept();
ObjectOutputStream oos = new ObjectOutputStream(connected.getOutputStream());
oos.writeObject(dPFPSample.serialize());
This the code that i used on server socket
Socket clientSocket = new Socket("localhost", 5002);
ObjectInputStream ois = new ObjectInputStream(clientSocket.getInputStream());
DPFPSample dpfpSample = (DPFPSample) ois.readObject();
i got an error java.lang.ClassCastException exception on ois.readObject() line
I would assume that your DPFPSamle.serialize() returns something different then DPFPSamle. I'd say you don't need to call any serialization method. The stream will handle it. So just call writeObject(dPFPSample)
In order for this to work your class (the one you are trying to send - i.e. DPFPSample) must implement the java.io.Serializable interface.