Emmanuel BENOîT
a4bce68b17
* Added a text file which describes the current client/server protocol, and the implementation of both the protocol itself and the server-level support. It also includes a discussion of what is wrong with the current implementation.
134 lines
No EOL
6.2 KiB
Text
134 lines
No EOL
6.2 KiB
Text
Communications between the server and its clients
|
|
==================================================
|
|
|
|
This file contains a few notes about the implementation of the client/server
|
|
system, as well as a (purely speculative) section about changes that ought to
|
|
be made.
|
|
|
|
|
|
Definitions
|
|
------------
|
|
|
|
The Legacy Worlds "server" has nothing to do with the web interfaces. It is a
|
|
standalone application which handles most aspects of the game itself, but does
|
|
not provide any kind of human-readable interface.
|
|
|
|
Legay Worlds "clients", on the other hand, are applications (whether they are
|
|
standalone or depend on some container is a detail) which connect to the
|
|
server and provide either some user interface or an intermediary layer for
|
|
an user interface application.
|
|
|
|
At this time, the two clients in existence are:
|
|
-> the main web site,
|
|
-> the administration web site.
|
|
|
|
This architecture was designed to keep any access to the game completely
|
|
separate from the game's logic. The only exception to that principle is the
|
|
email notifications system (see discussion).
|
|
|
|
|
|
Protocol implementation
|
|
------------------------
|
|
|
|
All client/server communications go through a RMI interface, SessionAccessor.
|
|
This interface can be used by clients to initiate, authenticate and terminate
|
|
sessions and to execute commands on the server. The general type of a session
|
|
(i.e. whether it is an administrative session, a game session, or an
|
|
"external" session which serves for user registration) is determined when the
|
|
session is created.
|
|
|
|
Commands are classes that extend the Command abstract class. They carry all
|
|
the information required for their specific purpose.
|
|
|
|
In response to a Command, the server will reply with either an exception or
|
|
a response. The following exceptions can be thrown by the server:
|
|
|
|
-> SessionInternalException means that some internal error occurred while
|
|
manipulating the session or executing the command. It can in theory be
|
|
thrown by all parts of the session access interface, but shouldn't
|
|
occur too often in practice, as it indicates a bug or server problem.
|
|
|
|
-> SessionIdentifierException means that the session identifier sent by
|
|
the client doesn't match any known session. This may indicate a timeout
|
|
on the client's part.
|
|
|
|
-> SessionStateException is thrown when the client tries to re-authenticate
|
|
a session or to execute a command before the session has been
|
|
authenticated.
|
|
|
|
-> SessionCommandException is thrown when the command that was sent is not
|
|
supported by the server.
|
|
|
|
When everything is fine, a command's execution will cause the server to return
|
|
an object of some class that inherits the CommandResponse class. If no data is
|
|
to be transmitted in response to the command, the response may be a
|
|
NullResponse instance.
|
|
|
|
|
|
Server implementation
|
|
----------------------
|
|
|
|
The server supports various types of session. Each type of session may have
|
|
different parameters (for example, its timeout) or behaviours (for example,
|
|
the way the session's authentication request is verified). In addition, each
|
|
type of session will implement a different set of commands.
|
|
|
|
The internals of the session and command routing system are somewhat outside
|
|
the scope of this document. The various classes which implement that system
|
|
can be found in com.deepclone.lw.beans.user.abst for the most basic elements,
|
|
while the com.deepclone.lw.beans.user.admin,
|
|
com.deepclone.lw.beans.user.player and com.deepclone.lw.beans.user.ext
|
|
packages all contain parts specific to session types.
|
|
|
|
Actual command handling is defined through classes which implement the
|
|
AutowiredCommandDelegate interface.
|
|
-> The getCommandHandler() method must return the class which defines the
|
|
type of session in which the command handler is to be included. For
|
|
example it will return GameSubTypeBean.class for game session commands or
|
|
AdminCommandsBean.class for administration commands.
|
|
-> The getType() method must return the class of commands handled. For
|
|
example, a handler for commands of the WhateverCommand class would have
|
|
this method returning WhateverCommand.class
|
|
-> Finally, the execute() method implements the command itself.
|
|
|
|
All command handlers, once defined, must be listed to one of the Spring XML
|
|
configuration files in the legacyworlds-server-beans-user project's resources.
|
|
|
|
|
|
Discussion
|
|
-----------
|
|
|
|
While the current implementation is successful in that it defines a clear line
|
|
between the game and whatever is used to display it and access it, it has a
|
|
few drawbacks.
|
|
|
|
Firstly, the use of RMI associated with dozens of Command / CommandResponse
|
|
classes, while easy to use, is definitely very heavy, specific to Java and
|
|
causes a proliferation of mostly-useless classes.
|
|
|
|
The protocol's weight is not too problematic at this time, since all
|
|
communications occur either on the same system or between virtual machines
|
|
running on the same system. However, the unbelievable amount of classes
|
|
makes the implementation of new commands or the modification of existing
|
|
commands somewhat tedious. Finally, the Java specificity would prevent the
|
|
implementation of clients connecting directly to the server in any other
|
|
language.
|
|
|
|
However the main problem with this implementation lies elsewhere. As a matter
|
|
of fact, communications between client and server only go one way: the clients
|
|
may request the execution of commands, but the server cannot send the clients
|
|
data independently. It is not possible to "poll" the server either: sessions
|
|
are exclusive and can only be used to execute one command at a time, so having
|
|
one session running a blocking command is not a possibility. The only way a
|
|
client application could request updates would be by running a command every
|
|
few seconds. This is not a problem at all with the current clients, as they
|
|
are based on user-triggered HTTP requests.
|
|
|
|
However, trying to implement anything more interactive would be difficult. As
|
|
a matter of fact, the email notifications system should *be* a separate
|
|
client, but the current architecture does not support it.
|
|
|
|
In the long run, the existing communications protocol should be replaced with
|
|
something more flexible. For example, it is entirely conceivable to replace it
|
|
with a custom TCP- or even UDP-based protocol which could be used by both
|
|
"local" clients (such as the web sites) and remote applications. |