patterncsharpMinor
Writing and reading of a custom binary protocol
Viewed 0 times
readingprotocolwritingcustombinaryand
Problem
I'm currently trying to develop some code that will handle parsing and building of a custom binary protocol. The protocol itself
is still fairly fluid but the basic core features are decided. These include
Basic format is: [STX][Header][Payload][Checksum][ETX]
Note: I can't use libraries like proto-buf .net as the protocol
specification itself is outside of my control.
Any comments on code styling, design, implementation, best practices etc welcome.
Here is what I have come up with so far:
Data streams
```
public interface IDataInputStream
{
string ReadString(int count);
char ReadChar();
int ReadInt32();
short ReadIn16();
byte ReadByte();
}
public class DataInputStream : IDataInputStream, IDisposable
{
private readonly BinaryReader _reader;
public DataInputStream(Stream stream)
{
_reader = new BinaryReader(stream, System.Text.Encoding.UTF8);
}
public string ReadString(int count)
{
return new string(_reader.ReadChars(count));
}
public char ReadChar()
{
return _reader.ReadChar();
}
public int ReadInt32()
{
return _reader.ReadInt32();
}
public short ReadIn16()
{
return _reader.ReadInt16();
}
public byte ReadByte()
{
return _reader.ReadByte();
}
public void Dispose()
{
_reader.Dispose();
}
}
public interface IDataOutputStream
{
void Write(char value);
void Write(string value, int length);
void Write(int value);
void Write(short value);
void Write(byte[] value);
}
public class DataOutputStream : IDataOutputStream, IDisposable
{
private readonly BinaryWriter _writer;
public DataOutputStream(Stream stream)
{
_writer = ne
is still fairly fluid but the basic core features are decided. These include
- It has a start and end deliminator
- It contains a header and payload set of data. The header is standard and contains information such as the payload type, time of sending etc
- Any strings or chars will be Ascii characters
Basic format is: [STX][Header][Payload][Checksum][ETX]
Note: I can't use libraries like proto-buf .net as the protocol
specification itself is outside of my control.
Any comments on code styling, design, implementation, best practices etc welcome.
Here is what I have come up with so far:
Data streams
```
public interface IDataInputStream
{
string ReadString(int count);
char ReadChar();
int ReadInt32();
short ReadIn16();
byte ReadByte();
}
public class DataInputStream : IDataInputStream, IDisposable
{
private readonly BinaryReader _reader;
public DataInputStream(Stream stream)
{
_reader = new BinaryReader(stream, System.Text.Encoding.UTF8);
}
public string ReadString(int count)
{
return new string(_reader.ReadChars(count));
}
public char ReadChar()
{
return _reader.ReadChar();
}
public int ReadInt32()
{
return _reader.ReadInt32();
}
public short ReadIn16()
{
return _reader.ReadInt16();
}
public byte ReadByte()
{
return _reader.ReadByte();
}
public void Dispose()
{
_reader.Dispose();
}
}
public interface IDataOutputStream
{
void Write(char value);
void Write(string value, int length);
void Write(int value);
void Write(short value);
void Write(byte[] value);
}
public class DataOutputStream : IDataOutputStream, IDisposable
{
private readonly BinaryWriter _writer;
public DataOutputStream(Stream stream)
{
_writer = ne
Solution
Protocol
It's strange to use a "custom protocol". Has no-one invented one you can reuse?
In a binary protocol with STX and ETX I'm used to seeing DLE being used as well:
... with DLE in the payload being escaped as `
It's strange to use a "custom protocol". Has no-one invented one you can reuse?
In a binary protocol with STX and ETX I'm used to seeing DLE being used as well:
.... with DLE in the payload being escaped as `
.
I was surprised to find no "total packet length" or "total payload length" field in the packet header.
Your protocol doesn't handle variable-length strings in the payload well.
A one-byte checksum is pretty small.
This protocol doesn't recover from transmission errors well: if you lose a byte, then because you don't use , you can't reliably find the start of the next packet (unless you guarantee that the STX char i.e. '$' is unique and never found in the header, not the payload, nor the checksum).
Text-based protocols can be easier to work with.
Code
Do you validate the received packet somewhere? Check that it starts with Stx, ends with Etx, and includes a valid checksum?
Your test code uses strings whose lengths are equal to the maximum field length; the receive code shows that short string will be zero-padded, but you don't have a unit-test for that.
BinaryReader is little-endian. Is your protocol little-endian too?
GetCommand returns data[1]. Should it return data[2]: maybe data[0] is the STX and data[1]` is the Identifier?Code Snippets
<DLE><STX> <PAYLOAD> <DLE><ETX>.Context
StackExchange Code Review Q#44625, answer score: 4
Revisions (0)
No revisions yet.