From: Snowdog <sn...@ga...> - 2013-11-15 01:21:41
|
I’ll tackle these inline… so see below. On Nov 14, 2013, at 1:54 PM, Mark Tarrabain <ma...@ly...> wrote: > Hey, > > Well, a recent and rather unexpected change in my employment status has > opened up my schedule a whole lot, and since I've really wanted to do > some work on this, I might as well take advantage of the time I have > right now to do so. Ironically the exact opposite has happened to me. I’m starting a new job and loosing lots of time. :-/ > So... first things first. > > It seems there is some sort of logical error in the client-server > connectivity, since I cannot seem to disconnect from a server that I've > connected to. The client side network module is new, and admittedly lacks some polish to put _very_ kindly. ;-) Yes, there indeed is a disconnection issue. The client/server do indeed disconnect, but they do so on their own whims (or so it seems). Its a thread based timing thing i believe. The async nature of the network code poses some _significant_ challenges to what would be otherwise simple setup/teardown of the network pipe. We have to arbitrarily wait while other modules do their syncing before actually shutting down the pipe. I’ll be the first to admit, sometimes I think I’ve dug myself into a huge hole with this design, but other times things slips together so simply and easily I know its going to work great down the road. All the hard stuff is up front, once thats handled module writers should have a simple time of adding to this design. Till then though… expect to loose hair lol. > Also, it's been a while since I looked at the code here and I'm not sure > I'm getting my brain wrapped around how the whole system is structured. Yeah, the base structure is…. different. Because of the multi-threaded modular nature of the core it makes visualizing how things work difficult. I’ll try to boil it down for you. Remember this is all OOD/P so there is little in the way of a ‘flow’ to follow. I’ll reference key classes as I go... Basically, we have 3 subsystems (Layers) that each run in its own thread by the “Engine” (common.core.engine.Engine) 1) Network Layer (common.core.network.NetworkServer & common.core.network.NetworkClient) The network manages all connections and network I/O using a pool of worker threads The network sends/receives ORPGMessages (common.core.ORPGMessage) to/from the Module Layer 2) Module Layer All features of the system are ‘Modules’, i.e. ‘chat module’, ‘whiteboard module’, etc. All modules register with the ModuleManager (common.core.engine.ModuleManager) via the module loader (server.core.ServerModuleLoader & client.core.ClientModuleLoader) They register what types of messages they receive & send, register interest in other modules, register gui components, etc with the Module Manager. This is a key point…. Modules CANNOT interact directly with other modules, they MUST go through the ModuleManager. 3) GUI Layer (common.core.gui.GUIManager) All GUI components for registered modules and handled as JPanels by a GUIManager. Each panel is controlled and managed by its respective owning module. > Snowdog, could you please walk me through how the module system works, > exactly? What does a client and server have to do to register a > module? Eventually we will be able to dynamically load modules, but currently only ‘core’ static modules are loaded via the respective module loader (server.core.ServerModuleLoader & client.core.ClientModuleLoader) The module loader then instances the module and calls its doRegistration() method (see bottom of ExampleClientModule.java). The module class handles it’s own registering with the ModuleManager. > How does a client module send or receive data from the server, > and how does a module on the server send or receive data from clients? Check out the Example modules (client.core.modules.ExampleClientModule ) Messages between the client/server or client/client(s) is accomplished using a simple header/data structure (based on a TCP/IP packet design) 1) Create an ORPGMessage 2) Set the message type so the receiver(s) know what module this is destined for 3) Set any header data [optional, but useful for small messages] 4) Set data payload [optional] 5) Create a MessageAddress (contains details for delivery of message) and set the destination for the ORPGMessage 6) Push the ORPGMessage to the ModuleManager via sendToNetwork() call. Note: The data payload will be sent as binary so the structure of the data is up to individual modules. Could be text, XML, binary, JSON, etc. As the data portion of the message will only be parsed by the receiving module (and then only if needed presumably) it greatly cuts down on message parsing times (as only header is parsed) > I am thinking of working on the chat/channel system, if you haven't > already started on that. I have not started on either as all of my work has been much lower level. > Once that's complete, I will work on a channel-based whiteboard that can > be viewed by all within the channel, which will ultimately function as > the channel's map. > > Mark It should be noted that the server does not need to have a module for a given module. As it only parses the message header (for addressing info) it does not NEED to handle the message, only route it to the correct client. This means that technically, you only need a client side module for most tasks. The server contains a special ‘fallback’ module called ‘DefaultRelay’ that accepts all unknown messages and simply forwards them based on their MessageAddress data. let me know if you need any more info. --Snowdog |