Client-server Web Game Questions

Started by
16 comments, last by Time4Tea 6 years, 2 months ago

Hi, this is my first post on here :-)

So, I've been discussing with a friend of mine about making a client-server web-based game, and I'm looking for some advice. The game would be a fairly simple 2D turn-based game, similar to a board game, which two people would play through the website. Here are my specific questions:

  1. I know this is fairly broad, but is there any recommended language for coding the server part? I've read that it could probably be just about anything, but I was thinking of using Java, so it could easily be run on either a Windows or Linux machine. Would that make sense?
  2. What is the best way of allowing the server to handle multiple games being played at the same time? I was initially thinking of having one central server process, which could 'spawn' a separate 'game server' process for each game on demand. But maybe that is unnecessary? Would it be easier to create multiple threads (for each game) in the same server process? We don't anticipate many more than about 30-40 games going on at once.
  3. For the web client, ideally we want to allow the playing 'board' graphic to be scalable, so it can be scaled automatically to fit any window/screen size (tablets, etc.). What is the best way to handle that? Can it easily be done with raster graphics, or is it better to use 100% vector? I have heard that the HTML5 Canvas might have some useful functionality - would anyone recommend using it?

As you can probably tell, I don't have much experience of writing client-server applications. If anyone can point me to any good online articles that might help, it would be much appreciated! :-)

Advertisement

Language doesn't really matter in this case, use what is most productive for you. If you needed to use C++ or something for performance considerations you would likely have an inkling of that ahead of time.

Frankly you're talking about an insanely low number of players. Consider MMO shards can often handle a couple thousand players at a time even in games with more or less real time movement(tons of information flowing both ways, packets, updating NPCs and other things). You're talking about a turn-based game with less than 50 or so games running at a time. Frankly you could probably have a non-threaded single server process handle all of that on your average computer without breaking a sweat. In terms of performance constraints I don't think you have to worry much about your setup as long as it is functional.

Couldn't comment on the web client portion as that is outside my area of expertise. Everything that gets rendered ends up raster, the only thing vector lets you do is essentially generate a properly sized raster image when you need it. Assuming what you're using supports it, it would give "better" result than pure bitmap graphics generally. There isn't really a silver bullet for 2d image resolution really, things either have to come in multiple sizes or they get stretched before being copied to the frame buffer.

Hi Satharis, thanks very much for your reply. Your comments about the server are very interesting and I'm sure it will save me some work, if I don't have to get into multi-threading. So, for a non-threaded process, basically each 'game' that is running could be a separate instance of a game object class, and the server process would manage which client communications are going to which?

Thanks also for the advice about 2D images. Although, if anyone has any specific experience with making scalable web games, I would greatly appreciate any tips they have.

Question 1:

Language doesn't matter very much on the server side. Java is a common choice. But you can choose whatever you're familiar with. Even javascript is an option, which has the advantage that your client and server are written in the same language. Along with choosing a language you will at the same time need to choose a network library.

Question 2:

You can't really have one thread per game, because player actions are driven by events like a player sending a message to the server. So the way this works is you have a listener that triggers whenever anybody makes a move, or when a timer triggers.

Now there's a choice to be made. Do you allow clients to persist connections to the server or do you make a "REST" api.

With persistent connections, there is less verification after the connection is made; you don't need to verify who is sending the data every time; you are able to associate some data with the connection. The server is able to send messages to the client without waiting for the client to ask for it. If the connection breaks you would need to handle that either as "user has left the game" or by allowing users to reconnect.

With a REST api, you would have a single connection per client action. The server is unable to reach out to the client, but the client could ask the server every so many seconds if it has something new. Each request would need to be authenticated to figure out which client or user it is coming from. The server has no visibility to if the client has disconnected. With this approach it is easier to have multiple servers, because the server does not have implicit state in the connection, so any server can respond to any request.

Question 3:

I don't know. As you think about this, also consider supporting retina displays, which have high resolution for the same screen size, therefore allowing more detail, but larger icons and fonts.

2 hours ago, Time4Tea said:

Hi Satharis, thanks very much for your reply. Your comments about the server are very interesting and I'm sure it will save me some work, if I don't have to get into multi-threading. So, for a non-threaded process, basically each 'game' that is running could be a separate instance of a game object class, and the server process would manage which client communications are going to which?

Sure. When you break it down the only things a server are doing are: checking for input(messages on the network or what have you) processing, and giving output(sending things back in this case.) How you want to divide that up is up to you, for a purely socket based server you would generally get a series of connections referencing each client that connects and then be checking them periodically for anything new, then just process game updates. That doesn't really change whether you have 1 game or 5000 games, you would just separate the state for each game into a series of classes and then iterate through and update them all.

That said, since the games are completely independent from each other you could theoretically update them all concurrently using threads, but I definitely wouldn't mess with threading anything unless you have a good reason to.

@King Mir: Ok, thank you for your comments.

Re. Question 1:

Sorry, when you say "choose a networking library", what do you mean by that? Do you mean the networking protocol?

Re. Question 2:

I think the persistent connection seems more appealing and is closer to what I had in mind. I have read that it can be achieved using 'web sockets', although I don't yet know much about how they work. Yes, I will have to code in some way that the system can deal with disconnections and allow a game to be resumed after a client reconnects.

Re. Question 3:

Ok, thanks. Yes, I think it would probably be best if we start with images at a fairly high resolution, and scale them down if necessary for smaller screens.

@Satharis: Ok, thanks again. It seems like the non-threaded server process is the way to go :)

On 1/28/2018 at 5:46 PM, Time4Tea said:

@King Mir: Ok, thank you for your comments.

Re. Question 1:

Sorry, when you say "choose a networking library", what do you mean by that? Do you mean the networking protocol?

Not protocol, library. With many languages there is a standard networking library, with others you have some choices. For those, you will need to pick a library. You can probably google "<language> networking library" for you language.

Ideally, you'd pick a language with an off-the-shelf server solution. Node.js is very popular these days. Python with asyncio. Java with Apache Thrift... lots of options, very little reason to deal with anything lower-level than those.

Tristam MacDonald. Ex-BigTech Software Engineer. Future farmer. [https://trist.am]

On 1/27/2018 at 4:49 PM, Time4Tea said:

I know this is fairly broad, but is there any recommended language for coding the server part? I've read that it could probably be just about anything, but I was thinking of using Java, so it could easily be run on either a Windows or Linux machine. Would that make sense?

Any server-side language that supports threading should work. Java, C, C++, Go. Single-threaded languages like Python and Javascript may need additional libraries to support concurrency.

 

Quote

What is the best way of allowing the server to handle multiple games being played at the same time? I was initially thinking of having one central server process, which could 'spawn' a separate 'game server' process for each game on demand. But maybe that is unnecessary? Would it be easier to create multiple threads (for each game) in the same server process? We don't anticipate many more than about 30-40 games going on at once.

Typically it's cleaner to have one thread to read and one thread to write, per player. So you are looking at two threads per player. If a game session has 8 players simultaneously, then you are looking at 16 threads per session. You do want to organize each game in a logical session in its own thread. It doesn't have to be a separate process.

 

Quote

For the web client, ideally we want to allow the playing 'board' graphic to be scalable, so it can be scaled automatically to fit any window/screen size (tablets, etc.). What is the best way to handle that? Can it easily be done with raster graphics, or is it better to use 100% vector? I have heard that the HTML5 Canvas might have some useful functionality - would anyone recommend using it?

HTML5 can scale raster graphics easily. You will get pixelation, but that's more of a design question than technical. Do you want the vector look, or do you want the bitmap look?

 

edit: pressed enter too soon.

25 minutes ago, alnite said:

Single-threaded languages like Python and Javascript may need additional libraries to support concurrency... Typically it's cleaner to have one thread to read and one thread to write, per player. So you are looking at two threads per player

Worth pointing out that (especially in languages like Python and Javascript) you generally wouldn't use threads in this way any more.

Servers today mostly use event-driven async IO instead of the old one-thread-per-client blocking model. All IO is handled on either a single thread or a small fixed-size pool of threads. Rather than performing blocking reads, those threads will register with an API like epoll/kqueue (usually via a language-specific wrapper API) to be notified when data is available to be read from the client. Writes will result in some sort of future, so that they don't block in that direction either.

You'll have a background thread pool (or background process pool, for Python/NodeJS) that does any heavy computations required, and returns them asyncronously to the IO pool (typically via futures, or async/await for high-level languages).

Tristam MacDonald. Ex-BigTech Software Engineer. Future farmer. [https://trist.am]

This topic is closed to new replies.

Advertisement