Advertisement

MMO Server questions

Started by December 15, 2013 06:19 AM
9 comments, last by hplus0603 10 years, 11 months ago

I am implementing a MMO server using TCP. Well, this server was already implemented before, but in single threaded way, and of course did not scale properly.

The single threaded version just polled all player sockets constantly, and the response times were atrocious with more than 15 players online.

So now, I decided to modify it to create a new thread for each player that connects, and use blocking sockets instead of polling.

First question, is this scalable enough? What kind of limit can I expect?

I usually heard that MMO servers usually cap out at 2000 online players per server, could I reach this kind of value by using one thread per player.or the cpu would bottleneck too much?

My server is installed on Amazon EC2, so bandwidth wont be a problem, the performance will all depend on my implementation.

Second, how to detect when one client dropped the connection in TCP.

Let's say that one thread on the server is blocked on socket.Read() and the client just dropped the connection (for example, crashed ).

How should this be handled, does the blocking read() interrupts if the connection is dropped or it hangs there until the thread is killed by the main thread?

In the current implementation, since the sockets do not block, the server just keeps track of the timestamp of the last message received and drops the connection when too much time passes without new messages.

I am implementing a MMO server using TCP. Well, this server was already implemented before, but in single threaded way, and of course did not scale properly.
The single threaded version just polled all player sockets constantly, and the response times were atrocious with more than 15 players online.

So now, I decided to modify it to create a new thread for each player that connects, and use blocking sockets instead of polling.
First question, is this scalable enough? What kind of limit can I expect?
I usually heard that MMO servers usually cap out at 2000 online players per server, could I reach this kind of value by using one thread per player.or the cpu would bottleneck too much?
My server is installed on Amazon EC2, so bandwidth wont be a problem, the performance will all depend on my implementation.

Second, how to detect when one client dropped the connection in TCP.
Let's say that one thread on the server is blocked on socket.Read() and the client just dropped the connection (for example, crashed ).
How should this be handled, does the blocking read() interrupts if the connection is dropped or it hangs there until the thread is killed by the main thread?
In the current implementation, since the sockets do not block, the server just keeps track of the timestamp of the last message received and drops the connection when too much time passes without new messages.


A thread per client is generally a horrible solution. An OS can pull this off but you have to consider the memory requirements of 2k threads, the cost of thread transitions and other things which in general will likely make this solution completely unusable. At the absolute worst you should learn how to use the select call to handle 32+ clients per thread in order to keep the thread counts down to something reasonable. At best on the target OS you didn't mention, find the appropriate API which is epoll for Linux, kevents for BSD and IOCP for Windows. Or, to save some time and effort, use Boost ASIO, libevent, libev or libuv to wrap up that side of things for you.

As to the error conditions on sockets, a dropped connection will return an error from recv. So, any wrapper around the low level sockets API should return the error and you need to catch them.

From the sound of things in general though. You have a LOT of learning to do before you are going to make a viable MMO server. I highly suggest you start with something a bit smaller such as just learning how to do a single connection properly which will teach you all the details you need to learn just on the sockets side. *THEN* scale up to a couple connections simultaneously to learn how they interact and finally at that point you can start thinking of your MMO server again. Of course the reality it that MMO servers are pretty huge beasts and realistically you will take a long time to learn all the bits and pieces which go into them.
Advertisement

I know how to use sockets, at least at a reasonable level, as I said I've got a complete of the server already working, and the client is already finished.

The only problem is that now I have around 50 players online at the same time and the single thread solution I used for the server does not handle it well.

I am doing this in Windows, with Winsock directly.

Can you give a quick explanation of that Select call?


I know how to use sockets, at least at a reasonable level

We obviously differ on what a "reasonable level" means as your questions are all "reasonably expected" that you know the answer before you tackle something this large. I'm not trying to be a complete ass here, just stating that your questions are very basic networking 101 items you should have learned. As to select, it was not really a seriously suggested solution, you should really be looking at IO completion ports on Windows for any real scaling. Of course that is a massive pain in the ass to use correctly and won't be covered here. At this point I suggest Google is your friend and you should look for "network api select" to find tutorials on that and/or "IO completion ports" to start the merry journey down the MS black hole of a crappy API's...

Don't use windows for your "mmo server."

It's not unreasonable on an actual Windows Server, but I can guarantee you there are decent existing solutions and/or guides for Linux and its cousins.

Not to mention that Windows servers tend to be more expensive for running the same tier of hardware compared to Linux on EC2.

Advertisement

Ok, I will try moving the server to linux, it is just a console app, so should be no problem I think happy.png

Also, when you start talking about large scale applications (MMO*), you probably should start studying distributed computing, load balancing, and IPC concepts in depth first before diving in. These are pretty advanced topics, and creating efficiently scaling systems is very difficult. It may also help to move from the mindset of one monolithic server process controlling the game to thinking in terms of multiple modular programs running in parallel to spread the work load.

and of course did not scale properly.
The single threaded version just polled all player sockets constantly, and the response times were atrocious with more than 15 players online


What the others have said: If you can't even do 15 players on a single thread without lag, then you're doing something wrong.
EverQuest did 150 players per zone over ten years ago, on not only single-thread, but single-core, single-CPU servers.

Btw: Windows *can* be used for servers. Aforementioned EverQuest used it. Arena.net (Guild Wars, GW2) does it. Xbox Live! also does it, and is a pretty big online gaming service. :-) It's sometimes a bit more painful or more expensive than Linux for many use cases, but if you know Windows and don't know Linux, it may be worth it to stay on Windows.

Really, unless the simulation code itself can't keep up with a 30 Hz update rate, then a single-threaded networked server should be able to keep up with up to 64 players just fine using select(), and probably 1,000 players if using single-threaded I/O completion ports. The way to add threads, if on Windows, is to then use more worker threads for the I/O completion ports that you tie your sockets to. And here, you should use one thread per core, not one thread per user.

Finally: If anyone thinks this means that I'd prefer to write servers on Windows, the answer is a resounding "no" -- I'm most effective on Linux and other UNIX flavors for servers. But Windows is not a "no go," and we shouldn't automatically dismiss it "just because."
enum Bool { True, False, FileNotFound };

I see, if everquest did it single threaded then my server should be also able to support more, I might be doing something wrong, or not getting enough bandwidth in EC2 (I'm using the free version for now, might be capped, I need to check).

I've heard about IO completion ports before and that is extremely difficult to use, so if linux would easier for me I might change to it. I dont know much about Linux though.

This topic is closed to new replies.

Advertisement