Explain how you would design a chat server. In particular, provide details about the various backend components, classes, and methods. What would be the hardest problems to solve?
Lets try to start with analyzing the server requirements
- Server coordinate the chat activity. The server need to be running at all times.S
- Server need to support a large number of clients.
- Server need to maintain a list of online and offline user.
Then lets try a typical user case see if we have everything covered. Here are the steps in this typical user case
- Client 1 signs online, changes his/her status.
- Client 2 signs online, changes his/her status.
- Client 1 send a request to 2 asking to be added to 2’s contact list.
- Client 1 approve the request, now 1 and 2 are in each other’s contact list.
- Client 1 and 2 send each other messages, messages delivered.
- Client 2 left the chat and sign off status of client B change.
- Client 1 sign off.
Some classes that will be needed in our application
class User // Contains user details and contact list class Request // Request from one user to another class Server // Perform clients register, and coordination of the different client
Here are some problem that we might need to consider.
- What if there are conflict between the data stored in the client machine and the server machine?
If the data are out of sync, we need to have a mechanism to decide which one is right. For example, the status we should probably sync on the local machine while the contact list we might want to sync on the server. - What if there are many users, say millions of them?
We might want to use distribute the application in many servers, and syncing will be a problem. - Handling multiple clients.
One reasonable design approach is to use one thread for reading input from each client but adds a central state machine representing the state of the server (using one more thread, to which each of the client threads pass messages through a shared queue). - Design for safe concurrency
The best strategy is to design your program to allow a very simple argument, by limiting your use of concurrency and especially avoiding shared state wherever possible. For example, one approach is to use concurrency only for reading sockets, and to make the rest of the design single-threaded.