Sign in to follow this  
BorgPidgeon

My Server Design

Recommended Posts

Hello, I am wondering if my server is using the best method or not. It is designed to handle multiple connections (500-2000 connections). The Design I have the server split into a few classes. 1) The GUI. 2) The Protocol 3) The Networking 4) The Database Interface GUI This is a standard windows form, not much interesting there. When the user clicks "Start" a separate thread is generated which contains the Networking class. Protocol This sits above the Networking and Database Interface classes. It *is* the game. Networking The networking class consists of 4 distinct threads. The listen thread is always listening for new connections, the receive thread is constantly reading all sockets to see if there is new data incoming, send thread loops through the send list and transmits data to the appropriate remote connection and the ping thread checks for lost connections then removes them. Database Interface This is a class that utilises ADO.NET to communicate, asynchronously with an MSSQL 2005 database. I believe that if there is a problem with my design it will be the performance of the networking layer. Does what I have explained sound efficient enough to handle 2000 connections or is there a better way?

Share this post


Link to post
Share on other sites
It's unlikely that network throughput will be the bottleneck. Assuming you pay a thousand bucks a month and get 100 Mbit/s to the internet, that's still only 10 megabytes per second -- one percent of the memory throughput of a modern CPU.

Your threads don't make sense, not because of scalability, but becuse of correctness. Dropped connections are best detected as a side effect of reading, both for TCP (because recv() will return 0) and for UPD (because you'll notice that you've gotten nothing from the endpoint for X seconds and time it out). New connections are also pretty well done in the reading loop, because select() will return a listening socket as readable when it's ready to accept().

From how you describe the problem, my advice to you would be to write your system as simple as you can, to make sure you get it working. Don't add threads or other complications unless you feel REALLY comfortable using them. Stay within your comfort zone. Once you have something up and running, for a real amount of time (i e, more than ten minutes), you should profile it and measure it, and fix problems only if you find any.

Share this post


Link to post
Share on other sites
"that's still only 10 megabytes per second -- one percent of the memory throughput of a modern CPU."

Interesting little fact, hplus! :)

My personal opinion on this question, Borgpidgeon, is that it is too hard to judge without more information. You say you're going to have a thread that listens, and a thread that receives/sends, but you don't say anything more than that. Theres a lot of ways you can do just what I listed above... a whole lot.

I recommend first off trying to establish more precisely what you wish to accomplish with this server (Is it fastest message relaying as possible you want? Or as many connections as possible? Do you plan on using TCP, UDP or a hybrid?) then try and see how others do it. Don't stick to the first design you find, though - look at all the code, why they did it that way, then move on to the next to see if they offer any better methods.

Share this post


Link to post
Share on other sites
Thank you for your responses. This is not a server I am intending to make, this is a server that I have made.

hplus0603: I had problems trying to use Socket.Select() in C#.NET if it will give me a performance boost I will try again though, could you confirm it would be better to use that as opposed to a separate thread?

The reason I have built the server in this way is that I originally intended it to be an IRCD. IRC only seems to know a connection drops by pinging it with text.

There is no, current, problem but I would like to know the most efficient way of doing this.

Quote:
Once you have something up and running, for a real amount of time (i e, more than ten minutes), you should profile it and measure it, and fix problems only if you find any.


This server is currently running, and has been for the past 5 days, as a chat server. This doesn't give it much of a stress test as it will only have a maximum of 25 connections at least until the company expands (I'm using my server code at work).

Share this post


Link to post
Share on other sites
When you have hundreds of threads, the cost of those thread stacks will start making itself known. Select() in .NET, however, probably suffers from the fact that you can't redefine FD_SETSIZE to anything greater than 64 in .NET, although I haven't verified that.

In the .NET framework, there is a nice asynchronous socket wrapper which uses IOCP, and lets you run one or a few threads to handle the completion. If you want the best scalability in .NET, that's what I would recommend.

Share this post


Link to post
Share on other sites
I do not have hundreds of threads, the networking section operates within four threads:

Listen
Send
Receive
Ping

These are continually looping. In addition to these threads there are several generated by .NET for the GUI and also asynchronous calls for database interaction (but should not be very many).

Now that you know I am not using dozens of threads would you still recommend altering the code to improve scalability?

Share this post


Link to post
Share on other sites

Create an account or sign in to comment

You need to be a member in order to leave a comment

Create an account

Sign up for a new account in our community. It's easy!

Register a new account

Sign in

Already have an account? Sign in here.

Sign In Now

Sign in to follow this