I'm designing an instant messaging server as a personal exercise to improve my understanding and application of multi-threading and design patterns in Java. I'm still designing, there's no code yet.
My goal is to have a server that should make effective use of a multi-CPU box. I'd like the server to be distributable across multiple boxes, but wonder if that's running before I can walk.
My initial thoughts are:
ClientConnectionManager
hasServerSocket
object that constantly accepts clientSocket
connections.ClientConnectionManager
has a thread pool that spawns a newClientProxy
object when a client socket connection is accepted, handing in the clientSocket
object.- The
ClientProxy
objects represent the client app and handles sending/receiving messages across theSocket
stream.
Is it correct that only one ServerSocket
may bind to a Port? I take it there's no way to have a pool of objects accepting Socket connections?
I have two ideas for passing messages between ClientProxy
objects. Either directly between ClientProxy
objects that are "buddies" or via a central "Exchange" object, or better yet, pool of objects.
What are the Pros/Cons of the two approaches? Does the Exchange lend itself better to a distributed app?
Would the Observer and Mediator patterns, respectively, be appropriate?
Best Answer
Correct. Only one thing can bind to a particular port on a given network interface at a time. Whenever a connection is received, a new socket is automatically created for the client on a deferred/internally-routed port. This is how a single listener can spawn any number of client handlers without waiting for the previous one to disconnect.
You can have clients receive a proxy to their their buddies' message queues whenever the buddies come online. They can then directly queue messages to each other, avoiding the need of a centralized exchange. The server would keep a reference to all of its online clients and notify the interested parties of their friends' connections/disconnections via the queue.
Scaling this to fill a single box would become a matter of adding network interfaces (or using a port range on the one interface). Scaling this across multiple boxes would require server synchronization / passing queue proxies to-and-fro willy nilly.