Designing a Scalable C Chat Server

Click For Summary
SUMMARY

The discussion focuses on designing a scalable C chat server using a callback system based on the Publish/Subscribe model. The proposed architecture allows multiple clients to connect to a dedicated server, facilitating modular communication and extensibility through third-party DLLs. The author emphasizes the importance of a standardized packet structure for network messages, which includes error checking and event handling. While the select function was used for managing connections, alternatives exist that may offer better performance.

PREREQUISITES
  • Understanding of C programming language
  • Familiarity with network protocols and socket programming
  • Knowledge of the Publish/Subscribe design pattern
  • Experience with event-driven programming concepts
NEXT STEPS
  • Research advanced socket programming techniques in C
  • Learn about alternative methods to the select function for managing connections
  • Explore the implementation of the Publish/Subscribe model in network applications
  • Investigate modular design patterns for extensible software architecture
USEFUL FOR

Software developers, network engineers, and system architects interested in building scalable chat applications or enhancing their understanding of event-driven network programming.

James889
Messages
190
Reaction score
1
Hi,

I developed a simple ad-hoc client/server chat program, however the design isn't exactly scalable since the addresses are hard coded and one of the clients is also the server.

So i wanted to write a dedicated server, to which multiple clients could connect and chat, like irssi..

how would you design something like this?
 
Technology news on Phys.org
Hey James889.

I did a design quite a while ago for networked protocols and the way I designed it was to use a callback system (think event system) where you created servers and clients where clients connected to servers with a global manager and any external program could register with these frameworks to get messages.

The registration method is known as Publish/Subscribe in the programming world and its just a fancy way of giving callbacks with the events that you want to subscribe to, to the framework so it can call the callbacks when something happens.

So in short, you create a server object for the server, a client object on the other computer and behind the scenes you have some way of sending and receiving data that is standardized for all network messages.

The way I did was that I used the select function, but there are way better ways to do the same thing in both Winsock and in the normal sockets library: I used it because I was familiar with it and because it worked but apparently some people say that using select is bad for performance.

What happens is that each connection has an internal double buffer and in the back-ground the client connection thread is both sending the data as soon as it can to where-ever and receiving data when it can.

All network messages have a standard header and as soon as the thread gets a complete packet (details are in the header) it constructs the packet and constructs a packet class using a class factory in which it creates the class and asks the class to handle that packet.

The class then does its thing and handles the packet by transforming the data into its own structures and it does whatever it needs to.

So in this scenario you have a chat-message-protocol packet and then you can put it whatever routines and information inside that packet.

The point of doing this is that the standard framework takes care of getting packets, constructing them, checking them for errors and then asking a specific interface to execute them. You can block packet-types directly from the centralized interface that you don't want and you can also do 3rd party stuff where you can say download a DLL or an SO and implement custom packet handling by an extension.

If you want to use UI routines then the appropriate modules subscribe to specific packet events, new network connections (client connections to a particular server) and other events to update the data in the UI and the module. Since this is all event based you just create the right publish/subscribe class which can be templated with a specific kind of data structure and register it with the network manager.

After you create the server, the UI and other systems register the events with the network manager given a server and the call-back method updates the UI and anything else.

That's the basic idea I used for doing network stuff and it worked really well. It takes a little bit of overhead to get it right, but when you do you can make everything modular that communicates with each other and updating the functionality is a lot easier as well.
 
Ouch, sounds difficult.
 
You don't have to do everything at once: do it bit by bit and if you don't want the flexibility of one feature, then leave it out and leave the skeleton there if you want to add it in later.

The way I did it was specifically so that the whole thing could be extended without modifying the original executable: it was built to be extended by third party DLL's and other such extensions.

If you want to design programs for easy extensibility, you need to do this but if you not, you can make different design decisions.
 

Similar threads

  • · Replies 29 ·
Replies
29
Views
5K
  • · Replies 9 ·
Replies
9
Views
4K
  • · Replies 18 ·
Replies
18
Views
4K
Replies
1
Views
3K
  • · Replies 3 ·
Replies
3
Views
2K
  • · Replies 15 ·
Replies
15
Views
3K
  • · Replies 4 ·
Replies
4
Views
3K
Replies
1
Views
2K
Replies
3
Views
3K
  • · Replies 25 ·
Replies
25
Views
23K