open two different socket input stream - java

I have a server and a client. The server receives two command strings: add or remove. If server receives add, it adds the object it receives from the socket to a local list. Is it acceptable to open two different streams consecutively to receive two different objects?
Example:
/* To read the command */
BufferedReader in = new BufferedReader(new InputStreamReader(socket.getInputStream()));
/* To read the object */
ObjectInputStream ois = new ObjectInputStream(socket.getInputStream());

No, that is not necessary. String is Serializable. You could do something like this:
String s = (String) ois.readObject();
Object o = ois.readObject();
if("add".equals(s)){
list.add(o);
} else if ("remove".equals(s)){
list.remove(o);
}
Just make sure you use ObjectOutputStream.writeObject to send both your command and object.

Related

socket closing early on multiple transfers

I'm trying to send an object over the network to another computer (or the same computer) and then have said computer send an object back.
On the sending computer, I send the object and receive the returned object:
ObjectOutputStream objectOutputStream = new ObjectOutputStream(socket.getOutputStream());
objectOutputStream.writeObject(object);
Object returnedObject;
socket.setSoTimeout(timeout);
try (ObjectInputStream ois = new ObjectInputStream(socket.getInputStream())) {
returnedObject = (Object) ois.readObject();
}
return returnedObject;
On the receiving computer, I receive the object:
Object object;
socket.setSoTimeout(timeout);
try (ObjectInputStream ois = new ObjectInputStream(socket.getInputStream())) {
object = (Object) ois.readObject();
}
return object;
and then send an object back:
socket.setSoTimeout(timeout);
ObjectOutputStream objectOutputStream = new ObjectOutputStream(socket.getOutputStream());
objectOutputStream.writeObject(object);
The error I get back is:
SEVERE: null java.net.SocketException: Socket is closed at
java.net.Socket.setSoTimeout(Socket.java:1137) at
and it occurs while attempting to send an object back on the receiving computer.
The socket on the sending computer is using the same address and port as the socket on the receiving computer.
This exception means that you closed the socket and then continued to use it. Specifically, you closed the ObjectInputStream at the end of the try-with-resources block where it is declared. That closes the other stream of the socket and the socket itself.
Don't use new object streams per transfer. Use the same ones for the life of the socket, at both ends.
You are using a very small-scoped try-with-resources:
try (ObjectInputStream ois = new ObjectInputStream(socket.getInputStream())) {
returnedObject = (Object) ois.readObject();
}
This code is interpreted as:
Get the input stream and build an ObjectInputStream around it.
Read an object from the object stream
Close the ObjectInputStream.
When you close the ObjectInputStream it automatically closes the InputStream that backs it, which is the socket's input stream. And the documentation of getInputStream says:
Closing the returned InputStream will close the associated socket.
You should make sure the try-with-resources has a bigger scope that covers the entire lifetime of the socket, or avoid using try-with-resources and make sure you close the ObjecInputStream properly when you are done with it or when there is an error.

How can I send a hashtable to my clientsocket?

I'm currently working on a small chat program, and for my next step I would like to send a hashtable to my clients, from my server.
However, so far I was using
PrintWriter out = new PrintWriter(socket.getOutputStream());
in my Server class, and
Scanner in = new Scanner(socket.getInputStream());
in my Client class, which were used to transport messages in form of strings from both sockets to the respective other end of the connection.
This does not work for Hashtables anymore, considering they are no primitive datatype.
What would I have to use instead to be able to send my Hashtable fully working to my client?
Since Hashtable implements the java.io.Serializable interface, you can serialize the object and send it over the socket's output stream:
Hashtable table = new Hashtable(); // TODO: avoid raw types
...
ObjectOutputStream oos = new ObjectOutputStream(socket.getOutputStream());
oos.writeObject(table);
oos.close();
To read the object in the client, you need to use an ObjectInputStream:
InputStream is = socket.getInputStream();
ObjectInputStream ois = new ObjectInputStream(is);
Hashtable table = (Hashtable) ois.readObject();

How to handle sending multiple messages over a socket connection?

I'm a bit of a beginner programmer so it's possible this is quite obvious and I'm overlooking the answer. But on to the question.
I have a two-part program (its a little more complicated than this example, but the situation is the same). The program has multiple messages fired between the client and the server. I have a PrintWriter on the server-side to send messages to the client, and on the client, I have a BufferedReader to read the messages sent.
When this example is run, I'm given two lines as output. The first message is both messages, and the second is NULL. What I am wondering is if there is a way to basically halt the server until I am ready for the second message, so that I can do something on the client-side before the second message is sent.
I am hoping to not use Thread.Sleep, as I would rather the Server wait around until the Client says it is ready.
This is the client:
public class Client{
public void run(){
Socket socket = null;
InputStream in = null;
BufferedReader reader = null;
try{
socket = new socket("LocalHost",1234);
in = socket.getInputStream();
reader = new BufferedReader(new InputStreamReader(in));
}
String messageFromServer = "";
try{
messageFromServer=reader.readLine();
}
System.out.println(messageFromServer);
String messageFromServer = "";
try{
messageFromServer=reader.readLine();
}
System.out.println(messagefromServer);
//close everything
}
}
This is the server:
public class Server{
public void run(){
ServerSocket server = null;
Socket client = null;
try{
server = new ServerSocket(1234);
client = server.accept();
}
PrintWriter writer = null;
OutputStream out = null;
try{
out = client.getOutputStream();
writer = new PrintWriter(out, true);
}
writer.write("Hi I'm a server");
//do some stuff that takes some time, user input, etc. etc.
writer.write("I'm still a server");
//close everything
}
Thanks :)
The problem with the way you currently have you code is the fact that you are using a BufferedReader, but the server is not terminating it's messages with a new line.
When you close the writer, the client is reaching the EOF or EOS and unblocking the read so it appears that both strings are being sent at once...
If you do something like...
writer.write("Hi I'm a server\n");
// This will force the message to be written to the client and picked up ;)
writer.flush();
writer.write("I'm still a server\n");
writer.flush();
Then you will get the messages seperatly...
You can use ObjectInputStream to read Objects instead of Strings.
This way you will read only one Message(String in your case) every call to ObjectInputStream.readObject();
BTW you can read the first message, "do something" and then read the second message. you don't have to read all of the sent messages at once.
If there are no other messages, then your thread will be blocked when trying to read an object from the ObjectInputStream.
Use it like:
ObjectInputStream inputStream = new ObjectInputStream( socket.getInputStream() )

Can't use InputStream from Socket after writeObject

Here is the situation:
I have a ServerSocket ss, and "Socket socket = ss.accept();", then if I do this:
istream = socket.getInputStream();
ostream = socket.getOutputStream();
in = new BufferedReader(new InputStreamReader(istream));
out = new PrintWriter(new BufferedOutputStream(ostream));
/*
I use in/out few times
everything OK
*/
ObjectOutputStream oos = new ObjectOutputStream(ostream);
oos.writeObject(someobject);
/* probably code that solves the problem */
String line = in.readLine();
On the client side I have this code:
PrintWriter out = new PrintWriter(new BufferedOutputStream(socket.getOutputStream()),true);
BufferedReader in = new BufferedReader(new InputStreamReader(socket.getInputStream()));
/*
using in/out, no problems
*/
ObjectInputStream ois = new ObjectInputStream(socket.getInputStream());
SomeObject so = (SomeObject)ois.readObject();
out.println("some text");
Everything is OK, until I send someobject. Client recieves object properly, no problems there. But I can't use socket anymore. If I do oos.close(), I get Exception that says "socket closed". If I do oos.reset() I get Exception with similar message. "socket reset". So what should I do? Is it possible to use same input and output streams after writeObject()?
What happens when I send "some text" is that I'm just getting nulls no matter how many times I call readLine(), I never get that "some text".
You can't use multiple type of stream/reader/writer on the same underlying socket. All your streams and readers and writers are buffered so they will all get thoroughly mixed up. Stick tone kind. Stick to one protocol. If you have object streams, use them for everything. And create them once for the life of the socket, not per message.

java serialized messages dont contain the correct data in socket-client-server model

hello i have a basic client-server system running using java sockets.
my problem is, that an object that i send from the client to the server does not contain the correct data after it has been sent once.
the first time i send it, it arrives with the correct values, but when i send it another time with different values, it still arrives at the server with the same values as the first time. it also happens if i send a completely different instance of that class. it always arrives with the data, which have been sent the very first time.
when i try this with other objects like java.lang.String it seems to work.
the problematic class looks like this:
public class Vector3f implements Serializable {
private static final long serialVersionUID = 2838034155614698213L;
public float x, y, z;
}
i use objectinputstream and objectoutputstream on both the server and the client to send and receive objects.
let me know, if you need any more information about the system.
thanks!
My guess is that you're changing the values of the fields and then retransmitting the same object. The ObjectOutputStream will notice that it's already sent the original object, and just send a reference the second time.
You could avoid this by calling reset() on the ObjectOutputStream - but I'd be tempted to just use separate instances anyway, possibly even making the class immutable. (Public mutable fields are almost never a good idea.)
The best way in case of serialization you should convert the object into a byte array object and then write into the socket.
// Serialize to a file
ObjectOutput out = new ObjectOutputStream(new FileOutputStream("filename.ser"));
out.writeObject(object);
out.close();
// Serialize to a byte array
ByteArrayOutputStream bos = new ByteArrayOutputStream() ;
out = new ObjectOutputStream(bos) ;
out.writeObject(object);
out.close();
// Get the bytes of the serialized object
byte[] buf = bos.toByteArray();
// Deserialize from a file
File file = new File("filename.ser");
ObjectInputStream in = new ObjectInputStream(new FileInputStream(file));
// Deserialize the object
Object obj = (Object) in.readObject();
in.close();
// Get some byte array data
byte[] bytes = getBytesFromFile(file);
// see Reading a File into a Byte Array for the implementation of this method
// Deserialize from a byte array
in = new ObjectInputStream(new ByteArrayInputStream(bytes));
in.close();

Categories

Resources