Skip to content

Commit 19f4839

Browse files
Create MessageProtocol.md
1 parent dd84ea1 commit 19f4839

File tree

1 file changed

+72
-0
lines changed

1 file changed

+72
-0
lines changed

MessageProtocol.md

Lines changed: 72 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,72 @@
1+
# Message Protocol
2+
Considering a client/ server model, where a type is serialized and sent over the network. In order to infer what the bytes represent on receiving end,
3+
we need to have some sort of metadata about the message.
4+
```c#
5+
server.BytesReceived += (clientId,bytes, offset, count) =>
6+
{
7+
// What did I receive??
8+
};
9+
10+
PureProtoClient client = new PureProtoClient();
11+
client.Connect("127.0.0.1", 11234);
12+
client.SendAsync(new SampleMessage() { sample = "Yo! Mr White" });
13+
14+
```
15+
Because of this, I have implemented an envelope class which acts as a metadata/header/carrier on top of an optional payload. Intention here is to be reusable on all network systems included in the library.
16+
The message envelope roughly looks as follows:
17+
```c#
18+
public class MessageEnvelope : IMessageEnvelope
19+
{
20+
public bool IsInternal {get; set;}
21+
public DateTime TimeStamp { get; set; }
22+
public Guid MessageId { get; set; }
23+
public string Header { get; set; }
24+
public Guid From { get; set; }
25+
public Guid To { get; set; }
26+
public Dictionary<string, string> KeyValuePairs { get; set; }
27+
}
28+
```
29+
Where any of the properties can be null/default and they wont be considered on serialization. You only send what you wrote.
30+
31+
Core network system identifies each session with a GUID.
32+
This Guid is also represents a ClientId for the server side of the TCP systems. in P2P systems such as Relay P2P or Room server this Guid identifies PeerId .
33+
Hence the ```From``` and ```To``` properties represens from peer to another peer on P2P cases.
34+
35+
```MessageId``` is used for async calls like ```MessageEnvelope response = await SendMessageAndWaitResponse(..., timeoutMs:10000)```
36+
when such method is called a MessageId is automatically assigned.
37+
Once the receiving end receives a message with a ```MessageId``` and sends a reply message with same Id, it will be caught by the sender will become the async response. its up to the developer how to filder such messages.
38+
39+
Note that when such async call is active/pending socket is not blocked, you can send as many messages as you want parallelly in between.
40+
41+
## Payload
42+
Payload is essentially an index for some bytes.
43+
### 1. Raw bytes
44+
```c#
45+
MessageEnvelope envelope = new MessageEnvelope()
46+
{
47+
Header = "ImageTransfer",
48+
Payload = bytes,
49+
};
50+
51+
// For byte segments, there is no extra copy here.
52+
envelope.SetPayload(Buffer, offset, count);
53+
```
54+
when sent through a network system this bytes will reach to its destination atomically.
55+
56+
### 2. A serialized message
57+
considering a method such as
58+
``` client.SendAsyncMessage(messageEnvelope, innerMessage); ``` The inner message will be serialized as byte payload.
59+
Receiving end is responsible to deserialize from the information provided by the message envelope.
60+
61+
``` c#
62+
OnMessageReceived(envelope)
63+
{
64+
SomeDataClass innerMesssage = envelope.UnpackPayload<SomeDataClass>()
65+
}
66+
```
67+
68+
## Remarks
69+
- MessageEnvelope and some internal messages are serialized statically with efficient binary encoding. See [SerializationBenchmarks](SerializationBenchmarks.md)
70+
- On receiving end, payload bytes are volatile. If the execution leaves the stack, bytes may be overwitten by next message. If you intend to store payload, either copy manually or call LockBytes() method of the message envelope.
71+
Unpacking / deserializing a message is safe since it inheritly does a copy.
72+
- Using message envelope without an inner message for simple information transfer or raw data transfer is way more efficient (3x) and reccomended.

0 commit comments

Comments
 (0)