4

The general question: how can I write a flexible, but not property heavy, messaging structure for sending TCP messages to clients and server?

Example:

I have a TCP Server for a game that sends some messages through TCP sockets to clients:

  1. Chat messages, including chat text, chat room, and speaker.

  2. Game messages, including game actions and events

  3. Client messages, including clients connecting, logging in, and disconnecting

To achieve this, when one of these actions occurs within the program, an event handler is called generating some specific event type.

ChatEvent with ChatEventArgs
GameEvent with GameEventArgs
ClientEvent with ClientEventArgs

These all extend the EventArgs class.

Now to my question. As things get more complex, I begin to cram more pieces of info into these EventArgs. My GameEventArgs start as

GameEventArgs gameArgs = new GameEventArgs(GameAction.Start);
gameArgs.gameId = "gameId123";
gameArgs.turn = "thisPlayersTurn";
JSON json = GameEventArgs.ToJson(gameArgs);
SendMessageToClient(json);

From this you can gather that GameEventArgs has some public properties such as gameId and turn. But a game is more than IDs and Turns. The client will need to receive game actions, which can be very complex. Suddenly the GameEventArgs needs more and more properties. This is fine, except, that only a few of these properties will be sent at a time. There could be 20-40 unused properties of GameEventArgs. Should I make more classes that inherit GameEventArgs, and only contain certain properties? I will be sending messages often, and I want to take the GC into consideration, as these messages are one time uses. (Should they then be IDisposable?).

Is there a better method to go about creating a messaging structure, where only a few of the defined properties of the message will be used at one time?

  • Using IDisposable has no effect on GC. You probably want to consider using structs rather than classes if you're concerned about GC performance. If the objects get large, you may need to pass them by reference to avoid unnecessary copying. – Jules Sep 20 '15 at 14:57
  • See command message and event message. Often in such cases, instead of passing an EventArgs type of message, you will want to create a custom class for each type of event that can occur. Each class will only have the properties needed for its event. It's okay/expected to duplicate properties across messages. – Kasey Speakman Oct 5 '15 at 21:07
  • Eh, ignore the XML / SOAP stuff in the links. EIP was originally written a while ago. If it were written today, it would probably say JSON or YAML / REST instead. – Kasey Speakman Oct 5 '15 at 21:12
1

This problem has been solved very elegantly by Google, in their protocol buffers project. It has some issues that you need to be comfortable. It is a binary format. The sender and receiver need to agree on the message type being transferred (but not the message type version), and last time I checked the C# implementations were not Google implementations (or followed their API style).

However, the plus of having a light weight (both bytes and CPU) message format, that copes well with out of version sync client/servers and has a lot of features by default for message specifications are a winner for me.

0

In your situation I would not use inheritance, except for a small amount of types maybe, where each type contains a set of properties that are usually used together.
I suggest using a single ID to encode your type of data. I prefer an Enum for that (Syntax is C++.net):

enum class EnumMessage
{
  MASK_Group = 1000000,
  Group_Chat   = 1000000,
  Group_Game   = 2000000,
  Group_Client = 3000000,
  ...
  Game_GameID = Group_Game + 1,
  Game_Turn   = Group_Game + 2,
  ...
};

Given an ID, you could find out the group by dividing by MASK_Group.

Alternative solution:
One Enum per class (GameEventArgs, ...), that encodes the data types.

The message itself would consist of multiple pairs of ID and actual data, e.g.
ID=1 data="content" ID=2 ...
If the data could contain the " character, I would omit it and add a length info instead, which in any case is safer.
Based on the existence of an ID in the received message you know which data you get. To decide which data you need to send, I would create static lists, that contain the IDs of the data you want to send.

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.