Mikeel
Mikeel

Reputation: 117

Java - serializable and sending object via socket

I receive an error:

IOException on socket listen: java.io.NotSerializableException: java.net.Socket

i try to send an object via socket with this code :

ObjectOutputStream outObjects = new  ObjectOutputStream(socket.getOutputStream());
outObjects.writeObject(currentPlayer);

output.flush();

second line gives error.... but i have serialized ( implements Serializable) the class Player (the class of the currentPlayer object) but one of the member of Player class is a Socket object..... i try to redefine and serializeble the socket object but no way to solve the problem.... where am i wrong ?

Upvotes: 3

Views: 8890

Answers (6)

Dirk
Dirk

Reputation: 31053

(Edited to answer the comment)

Try declaring the socket member as transient like in

private transient Socket socket;

This will inhibit the serialization machinery from trying to send the value of socket. Note, that you cannot meaningfully send objects holding values, which represent OS resources like socket handles, over to another process. In the best case, any attempt to use such an object on the receiving side will cause an exception to be thrown. In the worst case, such an attempt might introduce subtle bugs (data being sent to the wrong user). For this reason, such objects are never serializable (except if someone made a mistake).

Consider the following (simplified) example: on UNIX, a socket is represented by an integer number (the so-called file descriptor), which is returned by the OS when the socket is created. If this value is send to another process, there are no guarantees, that this number actually refers to a valid file handle open in the receiving process. Worse, if there is a file handle with the same numeric value in the receiving process, it is almost impossible to refer to the same socket open in the sending process. So, if the number is actually used as file descriptor in the receiving process when sending data, it will almost certainly go anywhere but the intended destination.

If sending and receiving processes are on the same machine, there are ways to transfer a "socket" over from one process to the other. But I doubt, that there are easy ways to access these OS calls from Java.

Upvotes: 1

josefx
josefx

Reputation: 15656

There are several ways to solve this problem, the fastest would be marking your Socket member transient. This ensures that javas default serialisation will ignore the Socket and your copy should contain null.

private transient Socket sock;

Alternatively you can provide your own serialisation methods, this requires that you write and read all members yourself. You can use the methods defined in Serializable (See below) or implement Externalizable instead.

 private void writeObject(java.io.ObjectOutputStream out)
     throws IOException
 private void readObject(java.io.ObjectInputStream in)
     throws IOException, ClassNotFoundException;

The cleanest would be separating your Players state from your network code, resulting in a class with only Serializable members. As a bonus the send class no longer contains invalid member fields.

Upvotes: 1

Thijs Wouters
Thijs Wouters

Reputation: 850

It means that the Socket class is not serializable.

You have to set the Socket member as transient, then it will not be serialized.

Just be sure to recreate the Socket object in a private readObject(ObjectInputStream) method, otherwise you can encounter null pointer exceptions.

Upvotes: 3

JB Nizet
JB Nizet

Reputation: 691635

A socket is not serializable because it's tied to the machine, OS, etc. it's executing onto. To be serializable, an object 's class must implement Serializable, and must contain objects that are all serializable, recursively.

So, to serialize your player, you must exclude its socket attribute from the serialization. You do this by declaring the attribute transient :

private transient Socket mySocket;

When the player will be deserialized, its socket will thus be null, and there's a good chance it won't work correctly. You should probably review your design, because serializing an object which needs a socket to work probably doesn't make sense.

Upvotes: 1

extraneon
extraneon

Reputation: 23950

implements Serializable does not in itself make an object serializable. Any and all serialized fields in the object itself must in turn be serializable (and any and all fields that they contain).

As a socket is not serializable you should not try to send it over the line. You can exclude it from serializing by declaring it as transient. The deserialized object then of course does not have a socket, so you also might want to check out the optional readObject and writeObject methods in your object which will be used for serialization and deserialization.

Check out this article on serialization.

Upvotes: 1

Gursel Koca
Gursel Koca

Reputation: 21280

You can not serialize Socket object, therefore you should make socket field transient. If you need some of socket properties, you can put extra fields to Player to represent these fields.

Upvotes: 4

Related Questions