4
\$\begingroup\$

I am currently writing a matchmaking server application for a 5vs5 UDK game.

Here is the scenario on which I built my code:

  1. The player starts the game and authenticate
  2. The player clicks an huge "Play" button and asks the server for an open lobby
  3. The server searches for a lobby and adds the player to the lobby found, and sends back lobby informations to the player so it can react accordingly (lobby id, players in lobby). Note that if no lobby is found (all lobbies are full, or there's no lobby at all) then a new one is created.
  4. The player (now in a lobby) selects a character and hits a "Ready" button.
  5. Once all players are ready, the server searches for an opposing team
  6. Once an opposing team is found, the server sends match infos (udk server ip and port) to all of the concerned players

I have written my matchmaking server with the C# Web Api template. This RESTful webservice can at the moment take care of steps 1, 2 and 3 as they are transactions between the frontend (player in UDK game) and the backend (the C# matchmaking server). The player asks for something, the server replies with JSON data. I have done so because having many HTTP requests seemed less foolish than having all authenticated players on a constantly alive TCP connection.

However, for the next steps (particularly the steps concerning what happens inside the lobby), I am undecise on what approach I should take. How can the server notify the players of new events (disconnections, new player, character chosen by a player, player ready...)? Should the players poll the server on a (very) regular basis for new events? Or would it be better to have a pool of threads to keep a TCP connection alive with the players in order to broadcast new events? Or something else? (UDP?). I'm kinda lost.

This is my first post so I hope it's not poorly phrased. Thanks.

\$\endgroup\$
  • \$\begingroup\$ Where/who will host the game once the match has begun? \$\endgroup\$ – John McDonald May 3 '15 at 21:11
  • \$\begingroup\$ The game will be hosted on a dedicated server. There's a pool of dedicated servers, and the matchmaking server will select any that is available. \$\endgroup\$ – Tom Solacroup May 3 '15 at 21:15
1
\$\begingroup\$

There are a lot of things that you need to consider. First of all, where are you hosting your servers? UDP works great if your hosting your own hardware, but if you're using something like AWS then you'll end up spending a lot of time trying to get a good reliable solution. UDP traffic can not be load balanced using the default load balancer, so you'll have to expose individual instances to the users. The same goes for Azure and Google services.

Also, if you're targeting mobile, then forget about UDP. Mobile data carriers have sporadic support for UDP. Sometimes it will work, other times it will not. I am aware that you can check if a user is on their cell network or using Wifi, but limiting the users to only play while they are wifi in order to use UDP is not a good solution in my opinion.

The best way I've found to support in-game events is either through sporadic polling over TCP from the client or long polling and TCP keep-alive sessions.

Sporadic polling is better if your requests are lightweight and atomic in nature. however if you need to guarantee order then go with a long polling keep-alive connection.

Keep in mind that you have a limit to how many sockets/threads you can create per box. Sockets are limited to something like 16 million(16,777,214 to be exact), but threads are much worse. With threads, it's possible to get a few hundred going, but that is not advisable. Threads require a chuck of contiguous memory in order to allocate the stack, so you will quickly run into the upper bounds of memory once you start to create/shutdown threads per connection.

Lightweight polling with atomic checking is by far your best choice if the server uses thread pooling and automatically handles keep-alive connection pooling.

Oh, and by atomic operations, I mean the following definition: Atomicity is a guarantee of isolation from concurrent processes(from Wikipedia). How you implement server-side atomic operations is another subject altogether, but for a quick reference, take a look at how CouchDB handles conflict resolution.

\$\endgroup\$
  • \$\begingroup\$ Thanks for the helpful answer. I noticed that there's no UDP socket implementation in unrealscript anyway. My only options are unsecured TCP communications through uscript's TcpLink (which won't do; I need players to authenticate in a secure way), or http requests, or implementing my own frontend through DllBind. I will surely go for the long polling or keep alive way with load balancing. I'm looking into nodejs and socket.io right now. \$\endgroup\$ – Tom Solacroup May 12 '15 at 13:49
  • \$\begingroup\$ I just ended up doing long polling with an HTTPS server. Of course it has its long-polling-related-issues, but I found no better alternative for udk. At least it works, and it's scalable. \$\endgroup\$ – Tom Solacroup Jun 30 '15 at 7:51
0
\$\begingroup\$

I would use the same method of communication that you will be using once the game begins. You're only delaying the inevitable by using these other methods. I don't know what you'll be using during the game, but now is the time to find out.

\$\endgroup\$
  • \$\begingroup\$ I'm using the standard UDK dedicated server once the game is ready to start (client-server model). There's no custom networking code involved. \$\endgroup\$ – Tom Solacroup May 4 '15 at 12:37
0
\$\begingroup\$

For a multiplayer game I'm creating I use a simple port system. Specific ports are used for specific traffic. So in my game I use ports 20551, 20552, 20553, 20554 etc, and each one serves a different purpose.

For example, port 20551 waits to receive update packets from a player containing their current position, rotation, etc. It takes this and distributes it to all other players so everyone in the session is synchronised.

In your game you could have a port for joining/leaving on your server. Send JSON data to this port containing whether it is a join/leave as well as information. If it is a leave request you will need to send the player's ID who just left so he can be removed from the session and you're not continually sending his data (such as position) to the other players after he is gone. Similarly with a join request you have to send down information about the joined players so the other players can be updated with the new data.

I recommend looking into the UdpClient class. You will probably also find you need to run methods asynchronously as the UdpClient.Receive() method used to wait for receiving data will hang your thread and freeze the application until it receives something.

I'll try and grab some source code for you tomorrow.

\$\endgroup\$
  • \$\begingroup\$ Should I rewrite my matchmaking server using mostly udp sockets then? Or do you think I can build upon what I've already done? I will try your method tomorrow. \$\endgroup\$ – Tom Solacroup May 3 '15 at 23:48
  • \$\begingroup\$ I would recommend rebuilding it using UDP, it simplifies it a lot when everything is the same. \$\endgroup\$ – user65803 May 4 '15 at 9:07
  • \$\begingroup\$ Another thing; When using UDP, how would the server know about unintended disconnections due to game crash, or internet failure? This may be needed to remove the dropped player from the lobby. \$\endgroup\$ – Tom Solacroup May 4 '15 at 9:09
  • \$\begingroup\$ In the XNA framework there is an OnExiting method which I use to send the request to the server. I would guess most frameworks have something similar. \$\endgroup\$ – user65803 May 4 '15 at 19:12
  • \$\begingroup\$ Of course there's such functionnality in the UDK. However if the client computer is unintentionally disconnected because of internet failure or computer crash it will never send the request. \$\endgroup\$ – Tom Solacroup May 5 '15 at 8:32

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.