Online game networking approach

Started by
3 comments, last by hplus0603 3 years, 1 month ago

Currently, I am using sockets for my network, with a REST-like approach. The packet contains json with a string of the controller and action to call. Next, the server will parse that content to determine what the client requests is about. Process some things then the server returns a json with a string controller and action back to the client, so the client can update a specific state.

But while doing this, I came upon rpc which is more straightforward than having to parse json with a string of controller and action.

Which is a better approach?

Socket like this or rpc?

or do you have any other better approach than this?

Thank you ?

Advertisement

“Using Sockets” is like saying “using networking.” Sockets is a network programming API, it's not a particular technology.

What protocol are you using with the sockets? TCP? UDP? Something higher-level, like HTTP, RTP, gRPC, DTLS, QUIC, or Websockets?

What is your game? Is it turn based, like chess? Is it action oriented, like a first person shooter? Does it use deterministic simulation, like an RTS? Does it have thousands of players, like an MMORPG?

If we knew more, we could probably give a better answer.

That being said – it sounds like your question is about “marshaling,” not about “networking.” “Marshaling” concerns how you pack and unpack your applications state into network packets (or other flat buffers, such as files, for savegames and such.) There's also probably a question about messaging structure in there?

Currently, it sounds like you're already using RPC – the client sends a RPC to the server, which does some processing, and sends a response. This is a (synchronous) procedure call. It also sounds like perhaps the server cannot initiate a call to the client? If so, the client would have to issue a “poll” command to hear about updates to the shared game state, which is generally very inefficient for real-time games, but can work OK for “base defense” or “farming” or “turn based” kinds of games.

What might be confusing here, is that many RPC packages come with their own “preferred” marshaling implementations. gRPC comes ,with Protocol Buffers, Unix-RPC comes with XDR Java Remoting comes with Java Serialization, and so on. But the marshaling is actually separate from the networking – you can use marshaling just for savefiles (like serialization in MFC) and you can use networking libraries with just blobs-of-binary-data (such as RakNet or ENet.)

So, without knowing more about what your gameplay is, and what your goal is, it's not really possible to give good recommendations. If your game is real-time-ish, the “general idea” is that each client sends a stream of events to the server, and the server sends a stream of events to the client, but those aren't necessarily tightly coupled in a request/response manner. If the client fires the gun, it sends the “client fired the gun” message to the server, and if someone gets hit on the server, the server sends the “someone got hit” message to the client. This way, it matters less “who” did it, and it matters more what the “outcome” is, which is why you have a server – to break ties and order events across multiple distributed players. Typically, games will do this using some form of binary serialization, on top of UDP. Each UDP packet starts with some framing information (clock information, sequence information, client identity, received other-way traffic informatino, crypto framing) and then there's a list of messages. Each message has a type, and a length, and the receiving side dispatches the message based on the type ID (typically using some table of function pointers, or hash table of reactor objects, or something like that.) Some timer will collect messages emitted by the game, and schedule them to be sent on some schedule, all packed into one datagram, for efficiency.

If you have more specific questions about the problem you're facing, perhaps you can share more details (without posting hundreds of lines of code, which really isn't helpful :-) ) and perhaps you can get a more detailed answer!

enum Bool { True, False, FileNotFound };

@hplus0603 Hi thanks for responding ?

My game is turn-based. 2 teams with 5 players each will take turns by group. Each team have 30 seconds to make their moves/actions. Team A first then after 30 seconds Team B…so on and so forth until one team wins.

My current network architecture is using Websockets TCP.

My question is, Is RPC approach more appropriate for this kind of game? I mean in my current setup, it is kind of a hassle to pack and put Controller string and Action string in the packet then parse it on the receiving end then have a routing function to determine the requested function.

Actually, after reading your answer I realized that my websocket setup and the RPC approach I think of is somewhat the same, it will just remove the routing part because in the RPC I can call specifically the function I want.

Additionally, I got curious about this part you said “Typically, games will do this using some form of binary serialization, on top of UDP. Each UDP packet starts with some framing information…” Can you tell me more about this? because right now I am just using plain json strings for my packets.

If you have links for me to learn more about these things is a great help.

Thank you. ?

Binary serialization works for native languages like C, C++, C#, Java, Rust, and so on.

Binary serialization is not particularly helpful if your game is in JavaScript or a derivative, because of the platform limitations that come with that.

Serialization is a long topic, and it is often made more complicated in existing frameworks, because they support serialization of “object networks” and not just “data.”

The basic idea is to send messages as structures, where you just binary encode (often, using memcpy) the data in the structures, although pointers of course don't work across address spaces, and thus need special handling. If you haven't worked with the bits-and-bytes of memory representation, you probably need to start there, before you go on to serialization, though.

enum Bool { True, False, FileNotFound };

This topic is closed to new replies.

Advertisement