Determine type of serialized object
I have a need to send messages (requests from the User to the Engine, and responses from the Engine to the User) over a socket. So the flow is essentially
+--------+ serialized request +--------+
| Server | <==== network ====> | Client |
+--------+ serialized res开发者_如何学JAVAponse +--------+
^ ^
| request/response | mouse/keyclicks
| object |
v v
+--------+ +--------+
| Engine | | User |
+--------+ +--------+
Now, it only makes sense to not reinvent the wheel here. I'm dealing with Java on both sides, so I plan use Objects like so:
/**
* A Client makes a Request.
*/
abstract class UserRequest implements Serializable {
/**
* The engine will call request.engineCallback(this);
* This will tell the Engine what the request is, at which point
* the Engine will determine its response.
*/
abstract EngineResponse engineCallback(Engine engine);
}
/**
* The Engine has calculated a Response.
*/
abstract class EngineResponse implements Serializable {
/**
* The User will call response.userCallback(this);
* This tells the User what the Engine thought of its request,
* and what happened as a result.
*/
abstract void userCallback(User user);
}
What I'm not following is, in my Server and Client sockets, how will I know what subclass of Request and Response is coming in? I see a situation like
Object request = in.readObject();
// now what? How do I know what to cast it to?
// Can I just cast it like
UserRequest request = (UserRequest)(in.readObject());
engine.addToRequestQueue(request); // let it take care of implementation details?
My first thought was to just pass everything through over Strings, but that seemed a bit silly when Java provides Serialization. But how do I make sure I know what class came across the wire? For that matter, do I need to know, as long as I only send decedents of UserRequest to the server and EngineResponse to the client?
Just use the instanceof
keyword provided:
Object o = in.readObject();
if (o instanceof SomeUserRequest)
{
SomeUserRequest sur = (SomeUserRequest)o;
..
}
else if (o instanceof OtherUserRequest)
{
..
}
For your protocol to be usable with simple serialization, you'll need to have all classes to be sent available on both sides of the connection.
And your engineCallback()
method will be executed on the server, not be a real callback to the client.
If you want more (like invoking methods on the other side, and passing classes not yet available on the other side), you may want to have a look at RMI (remote method invocation). It is based on Java serialization for the protocol, but adds method calls and the ability to pass unknown classes to the other side to be executed there.
精彩评论