Welcome, Guest. Please login or register.

Login with username, password and session length

 
Advanced search

1411279 Posts in 69323 Topics- by 58380 Members - Latest Member: bob1029

March 28, 2024, 01:37:13 PM

Need hosting? Check out Digital Ocean
(more details in this thread)
TIGSource ForumsDeveloperTechnical (Moderator: ThemsAllTook)Help with networking
Pages: [1] 2
Print
Author Topic: Help with networking  (Read 2311 times)
pengu2
Level 0
**



View Profile WWW
« on: April 25, 2019, 02:23:45 AM »

Hi, i've been looking for some solutions for creating a scaleable multiplayer game. So far i've been tinkering around with some C# libraries as C# is the language i'm most familiar with, i've found that most big multiplayer games has a server written in one language (often java) then their client is written in another language. I was wondering if i can achieve almost the same scaleability as them while using C# libraries on both server and client and also if there is any downside to using C# instead of Java creating the server. Also if anyone knows a good networking library for C# feel free to let me know!

To help clarify the question i'm not thinking of creating a huge MMO, its gonna be a turn based game with matchmaking.
Logged

SamSerious
Level 0
***


View Profile
« Reply #1 on: April 25, 2019, 09:57:42 AM »

I'm not a C# guy, but I've seen a lot of Unity3D devs use https://www.photonengine.com/en-US/Photon , maybe it's a solution for you.

Tho, independently of the language, turn based networking is actually on the simpler side. You could directly connect player-player via TCP, exchange the turn moves, and execute them on both sides. As long as your game logic is deterministic (e.g. both use the same, deterministic randomizer), it should just work.

Defer match making and server stuff for later, when you actually need it. Until then, exchange the IP addresses with your friends and test your game. If you run bigger tests, invite people to discord and let them exchange IPs.

Have fun!
Logged
pengu2
Level 0
**



View Profile WWW
« Reply #2 on: April 25, 2019, 11:03:39 AM »

Wouldn't the problem with direct communication between clients without an authoritative server be that cheating is pretty much straight forward?

Edit: I found this https://grpc.io/ which looks promising, its open source and completely free. It's not used for games though but i think it might work anyway
Logged

qMopey
Level 6
*


View Profile WWW
« Reply #3 on: April 25, 2019, 03:25:36 PM »

I just implemented a secure protocol over UDP that lets players authenticate and connect to dedicate servers, and has a reliability layer over UDP as well. Would be useful for any multiplayer game. Did you want to try asking some specific questions regarding your game?

For your turn based game you can use TCP. I think all your complexities would come from serialization and security. I'm sure there are tons of solutions out there for setting up secure connections with TCP in C#, and the same goes for serialization libraries. I do know protobuffers from Google has bindings to pretty much every language under the moon, so you might like this for serialization. Either that, or look up some JSON C# libraries, I'm sure there are plenty of options.

For security you can use HTTPS for authentication, for example with something like OAuth. You should definitely try to offload initial authentication to some other library or service. From there establishing some encryption keys for your TCP sessions should be very easy.
Logged
SamSerious
Level 0
***


View Profile
« Reply #4 on: April 25, 2019, 04:09:20 PM »

if both sides execute the turn based on synchronized moves, then both sides are servers, one side "cheating" will lead the game to be out of sync. Hence you can ruin the game (make it unplayable, just as if you'd just log out mid session), but you rather cannot cheat in the sense that nobody validates your false/fake input.

However, you can still cheat the same way as with authoritative servers, e.g. make all enemy units visible etc.
Logged
SamSerious
Level 0
***


View Profile
« Reply #5 on: April 25, 2019, 04:33:53 PM »

I think all your complexities would come from serialization and security.
serialization would be overkill in that case. you only need to send high level commands to both sides.
Imagine a chess game,
"select unity at G6"
"move to F5"
both sides would validate and execute that move.

From a programming point of view, you would create
- at the bottom level the "game logic/move engine".
- "command queue", that feeds the "game logic/move engine"
- "selector" that accepts move command either from player A or player B and passes it to the "command queue"
- "network layer" that passes commands from either side to the other side, the receiving commands are passed to the "selector"
- "intput layer" which basically translates keyboard, mouse, gamepad actions into commands that are broadcast to the "network layer"


ascii art would be kinda
Code:
+---------+
| input   |
+---------+
    |
+---------+  +----------+
| Network |--|Other side|
+---------+  +----------+
    |
+---------+
| selector|
+---------+
    |
+---------+
| command |
| queue   |
+---------+
    |
+---------+
| move    |
| engine  |
+---------+
The point of the command queue is that you can store it, replay it, to find bugs or even check cheating attempts that caused de-sync.
For single player, you could also add AI that would feed the selector or the command stack directly.

both sides combined would look like:
Code:
+---------+  +---------+
| PlayerA |  | PlayerB |
| input   |  | input   |
+---------+  +---------+
     |            |
+---------+  +----------+
| Network |--| Network  | <-- that's for multi player over network, you could just as good play hot-seat on one PC as
+---------+  +----------+     nothing below really cares where the commands are coming from
     |            |
+---------+  +---------+
| selector|  | selector|  <-- the selector can filter non-game commands, e.g. chat into a chat window
+---------+  +---------+
     |            |       <-- from here, everything is sync, cause no matter in what order commands of Player A or B
+---------+  +---------+       arrive, the selector passes only command from the active player
| command |  | command |
| queue   |  | queue   |
+---------+  +---------+
     |            |
+---------+  +---------+
| move    |  | move    |
| engine  |  | engine  |
+---------+  +---------+

That's of course just one of many possible solutions.

Logged
pengu2
Level 0
**



View Profile WWW
« Reply #6 on: April 26, 2019, 02:40:15 AM »

I just implemented a secure protocol over UDP that lets players authenticate and connect to dedicate servers, and has a reliability layer over UDP as well. Would be useful for any multiplayer game. Did you want to try asking some specific questions regarding your game?

I think my main question is what is best to use for a turn-based game like hearthstone, TCP or UDP. Players will have accounts so authentication will probably be done over OAuth or something similar. Also if matchmaking should be done separately from the game server?
Logged

pengu2
Level 0
**



View Profile WWW
« Reply #7 on: April 26, 2019, 02:41:10 AM »

if both sides execute the turn based on synchronized moves, then both sides are servers, one side "cheating" will lead the game to be out of sync. Hence you can ruin the game (make it unplayable, just as if you'd just log out mid session), but you rather cannot cheat in the sense that nobody validates your false/fake input.

However, you can still cheat the same way as with authoritative servers, e.g. make all enemy units visible etc.

The only problem then would be latency for people playing far apart?
Logged

SamSerious
Level 0
***


View Profile
« Reply #8 on: April 26, 2019, 06:08:27 AM »

if both sides execute the turn based on synchronized moves, then both sides are servers, one side "cheating" will lead the game to be out of sync. Hence you can ruin the game (make it unplayable, just as if you'd just log out mid session), but you rather cannot cheat in the sense that nobody validates your false/fake input.

However, you can still cheat the same way as with authoritative servers, e.g. make all enemy units visible etc.

The only problem then would be latency for people playing far apart?
how is latency in a turn based game relevant?
Logged
pengu2
Level 0
**



View Profile WWW
« Reply #9 on: April 26, 2019, 06:37:11 AM »

if both sides execute the turn based on synchronized moves, then both sides are servers, one side "cheating" will lead the game to be out of sync. Hence you can ruin the game (make it unplayable, just as if you'd just log out mid session), but you rather cannot cheat in the sense that nobody validates your false/fake input.

However, you can still cheat the same way as with authoritative servers, e.g. make all enemy units visible etc.

The only problem then would be latency for people playing far apart?
how is latency in a turn based game relevant?

True, idk what i was thinking. Might be extreme cases where latency is like 10+ seconds but that wouldn't be any different using any other method
Logged

qMopey
Level 6
*


View Profile WWW
« Reply #10 on: April 26, 2019, 11:33:08 AM »

You can't solve 10+ seconds of latency with networking code. That's more like an ISP problem!

To actually use TCP fundamentally you just need to send data from point A to point B. Any kind of data works. The earlier suggestion about transforming your game inputs into events is a great one.

Since you're making a turn based game your networking can be dead simple. For example, say all actions the player can take are represented within an enum. There's an enum value for selecting something, placing something, etc. Your networking can simply be a series of enums sent from one end to the other, each representing player actions. Then, each end can validate whether or not the move is acceptable given the current game state (no out of turn or illegal moves).

It's so simple you could actually implement the majority of your game in single player and add networking at the end. I don't recommend this, but it is true for most turn based games.

I wouldn't worry about it. Start tinkering with some TCP library that provides something like RPCs (remove procedure call), or a nice way to send events/serialize messages. Start implementing some gameplay and experiment. You will figure it out without too much trouble, and can always come back with specific questions.

Later on you can figure out how the matchmaker and the authentication works. These are isolated problems that you shouldn't worry about yet. For example, you can (and should) start with a basic matchmaker that simply stores a list of players who want to play and pops two off of the front and has them play together. You can implement this very easily once you have some gameplay ready to go that has been tested on your local loopback.
Logged
poohshoes
Level 0
**



View Profile WWW
« Reply #11 on: April 29, 2019, 06:54:30 PM »

I've used C# server code for hobby projects and never had any problems, and I can't see why it would be a problem.  Also I've used the lidgren library with C# and found it easy to use.
Logged

pengu2
Level 0
**



View Profile WWW
« Reply #12 on: April 30, 2019, 02:41:24 PM »

Hey, so after a couple of days of prototyping with https://grpc.io i feel like this solution will only make things harder for me mostly because its only client-server oriented, not to mention to get a secure connection i would need to buy a SSL-certificate which is quite expensive. I started looking for other TCP solutions in C# but i couldn't find any that meet my requirements.

So now as it feels like i've hit a dead end with TCP i decided to look into the Lidgren library which offers reliably ordered messages via an UDP connection to be sent. My question now is how secure is connection done with Lidgren, can i prevent packet sniffing by just encrypting exposed messages? I know ip spoofing is a thing too so is there a way to counter this with Lidgren?
Logged

qMopey
Level 6
*


View Profile WWW
« Reply #13 on: April 30, 2019, 05:09:38 PM »

Yes you are right, anything using TLS (HTTPS, and gRPC both use TLS) will require certs, and it costs money to get your cert recognized by a Certificate Authority.

I did a quick search. It looks like Lidgren has symmetric encryption implemented with a secret key. Here is some info: https://github.com/lidgren/lidgren-network-gen3/wiki/Message-Encryption

Unfortunately you can not get away with encryption alone if you want your network to be secure. You also need to authenticate users somehow, and it looks like lidgren doesn't do this. I searched a little bit for solutions, and someone did a little work here: https://github.com/SleeplessByte/lidgren-srp6a. I have no idea how good or bad this solution is. Maybe you can use this.

So it is good that lidgren has a feature for encrypting data, but you will need to use something else to securely setup a shared secret key between your client and your server. By the way, you want to use client-server architecture. You do not want to do anything else. Peer to peer is outdated technology. We can discuss more in-depth as to why you want client-server over peer-to-peer if you like.

I think most bigger games use something like OAuth to authenticate players over HTTPS, and then communicate a secret key to the game server and the player. They then can communicate over something like lidgren using the shared secret key, that is only valid for one login session.

I will recommend you use TCP and libsodium for security. With libsodium you can use public key cryptography to trivially get your game working securely. libsodium is a very high quality encryption library and has the best API I have ever seen (it is really simple). It is used in AAA games, and I myself use it for my own game. It has C# bindings here https://github.com/adamcaudill/libsodium-net, and docs here https://bitbeans.gitbooks.io/libsodium-net/content/.

You should use a secret/public key pair, generated by libsodium (it is just two byte arrays each filled with random bits). I recommend you hard-code a secret key in your game server. This is used to decrypt messages from clients. Clients can initiate a connection by encrypting messages with the public key. Clients can not open or read messages encrypted with the public key. Only the server, who has the matching secret key, can decrypt these messages. You should use the sealed box API from libsodium https://bitbeans.gitbooks.io/libsodium-net/content/public-key_cryptography/sealed_boxes.html.

Now you have a way for a client to securely send any data to the server. For example, you can implement a Terraria-style login with username + password, and the client can use libsodium to generate a symmetric key and send it along as well. Then the client and server can use symmetric encryption with the key the client picked to communicate from then onward: https://bitbeans.gitbooks.io/libsodium-net/content/secret-key_cryptography/authenticated_encryption.html, assuming the username + password were valid.

I think this is the simplest way to get your game working. You can use libsodium to build a different login solution later down the line if you choose to. For example, if you use OAuth later you can still use libsodium for symmetric encryption. I am simply recommending you setup the simplest possible authentication for now, and later on when you have a better understanding of exactly what you need, you can setup something else, and your familiarity with libsodium will still be valuable at that point.

Using TCP + libsodium will be very similar to using lidgren, except you can also trivially add in basic authentication (which is missing from lidgren).
« Last Edit: April 30, 2019, 05:17:30 PM by qMopey » Logged
Daid
Level 3
***



View Profile
« Reply #14 on: April 30, 2019, 09:32:47 PM »

Yes you are right, anything using TLS (HTTPS, and gRPC both use TLS) will require certs, and it costs money to get your cert recognized by a Certificate Authority.
Quick note, you don't need a cert that is recognised by a Certificate Authority. That's only useful in certain cases, which are not very applicable on game development (unless you do web development)
Logged

Software engineer by trade. Game development by hobby.
The Tribute Of Legends Devlog Co-op zelda.
EmptyEpsilon Free Co-op multiplayer spaceship simulator
pengu2
Level 0
**



View Profile WWW
« Reply #15 on: May 01, 2019, 03:05:53 AM »

By the way, you want to use client-server architecture. You do not want to do anything else. Peer to peer is outdated technology. We can discuss more in-depth as to why you want client-server over peer-to-peer if you like.

Thanks for the well put answer, got a lot of useful information from it! But as you stated that client-server architecture is what i should go for, does that rule out all communication started by the server? Let's say for example instead of having to constantly ask for new updates from the client to the server. Wouldn't it be better to just send an update from the server once there actually is something to send, like for example a player moved in a grid?

Edit: It would be done by simply connecting users in the server code and once one user sends a message, send back his update to everyone else in the same room

Edit edit: I found this before but thought it wouldn't be secure, but as you've mentioned i only need a way to encrypt and authenticate. Would this be a good solution for TCP https://docs.microsoft.com/en-us/dotnet/framework/network-programming/using-tcp-services. I think i'm skeptical because they mention that opening a connection can be explained as opening a stream, which sounds like there could be some security flaws too. I.e someone could write anything to said stream after they have authenticated themselves
« Last Edit: May 01, 2019, 03:56:40 AM by pengu2 » Logged

qMopey
Level 6
*


View Profile WWW
« Reply #16 on: May 01, 2019, 11:21:27 AM »

Your link looks like a typical way to start up a TCP connection. Stream just means a sequence of bytes. TCP packets are like a stream since they arrive in order. To make a TCP connection secure you need to encrypt your data and authenticate it. This happens with functions that operate on the data coming from the TCP connection, or on data you will send through TCP.

In other words the security happens on local buffers of data before its sent on the wire.

The libsodium docs I sent you earlier will be your best resource for learning how to do encryption and authentication. It’s just a few functions, and isn’t too scary.

You can use that TCP api you linked as long as you use something like libsodium to process all the TCP data.
Logged
pengu2
Level 0
**



View Profile WWW
« Reply #17 on: May 01, 2019, 11:25:11 AM »

Your link looks like a typical way to start up a TCP connection. Stream just means a sequence of bytes. TCP packets are like a stream since they arrive in order. To make a TCP connection secure you need to encrypt your data and authenticate it. This happens with functions that operate on the data coming from the TCP connection, or on data you will send through TCP.

In other words the security happens on local buffers of data before its sent on the wire.

The libsodium docs I sent you earlier will be your best resource for learning how to do encryption and authentication. It’s just a few functions, and isn’t too scary.

You can use that TCP api you linked as long as you use something like libsodium to process all the TCP data.

Thanks, i think that's all the info i need, i'm very grateful for your patience! I will return with further questions if i stumble upon any! Thanks again!  Hand Thumbs Up Left
Logged

qMopey
Level 6
*


View Profile WWW
« Reply #18 on: May 01, 2019, 11:25:45 AM »

Client server architecture means the game is simulated on the server, and the server is the boss. Other than that the idea is open ended.

The client only needs to initiate when starting up a connection. That’s why the server will use a tcp listener socket. Once the TCP connection is started you can send data however you like. It’s completely up to you. Just make sure the server is the boss, and enforces the game rules. The client should mostly just be sending the server “actions” or “moves”, to tell the server what it wants to do. If the server allows those moves, it can tell the client any necessary game updates.

Keep posting up any other questions! This is a fun topic to discuss, and this thread will be valuable for other people google searching around in the future.
Logged
pengu2
Level 0
**



View Profile WWW
« Reply #19 on: May 01, 2019, 12:48:48 PM »

Client server architecture means the game is simulated on the server, and the server is the boss. Other than that the idea is open ended.

The client only needs to initiate when starting up a connection. That’s why the server will use a tcp listener socket. Once the TCP connection is started you can send data however you like. It’s completely up to you. Just make sure the server is the boss, and enforces the game rules. The client should mostly just be sending the server “actions” or “moves”, to tell the server what it wants to do. If the server allows those moves, it can tell the client any necessary game updates.

Keep posting up any other questions! This is a fun topic to discuss, and this thread will be valuable for other people google searching around in the future.

Well might as well ask this here then since if i want to use the link i sent i gotta decide how connections are managed. What is best practice, a multi-threaded server with a new thread for each connection or is there some better solution?¨

Edit: For people googling and finding this, there seems to be easier solutions that build upon .Net sockets which is the link i was referring too.
https://github.com/MarkioE/Networker
https://github.com/chronoxor/NetCoreServer
Although the second link seem to have better documentation (the first links documentation seems to be under reconstruction) i believe both of the libraries should be able to scale well for bigger applications. The difference between is that the first link uses formatters to send packets and the latter just uses byte streams
« Last Edit: May 02, 2019, 04:07:35 AM by pengu2 » Logged

Pages: [1] 2
Print
Jump to:  

Theme orange-lt created by panic