I coded this simple protocol but I'm sure that it can be better, this is the process:
- Reads incoming data
- Waits until payload size can be read
- Reads the full message
- Checks if there are mixed messages
- Reads incoming data again
Code:
private async void ReadPackets(StreamSocket socket, SocketInformation socketInformation)
{
byte[] data = new byte[BufferSize];
IInputStream inputStream = socket.InputStream;
IBuffer buffer = data.AsBuffer();
while (socketInformation.open)
{
IBuffer bytesRead;
try
{
bytesRead = await inputStream.ReadAsync(buffer, BufferSize, InputStreamOptions.Partial);
if (bytesRead.Length > 0)
{
PrintByteArray("Data", data);
}
}
catch (Exception)
{
break;
}
// Wait for payload size
if (buffer.Length >= 4)
{
int commandType = (int)BitConverter.ToInt16(data, 0);
int payloadSize = (int)BitConverter.ToInt16(data, 2);
int packetSize = PacketHeaderSize + payloadSize;
// Wait for full packet
if (buffer.Length >= packetSize)
{
byte[] packet = new byte[packetSize];
System.Buffer.BlockCopy(data, 0, packet, 0, packetSize);
Debug.WriteLine("Packet received.");
ConcurrentQueue<byte[]> packetReceiveQueue = socketInformation.GetPacketReceiveQueue();
packetReceiveQueue.Enqueue(packet);
if (buffer.Length > packetSize)
{
int bufferLength = (int)buffer.Length - packetSize;
byte[] newData = new byte[BufferSize];
System.Buffer.BlockCopy(data, packetSize, newData, 0, bufferLength);
data = newData;
buffer.Length = (uint)bufferLength;
}
}
}
}
Debug.WriteLine("Socket closed.");
inputStream.Dispose();
socket.Dispose();
}