Асинхронный TCP-сервер - Советы по созданию сообщений

У меня есть асинхронный сервер сокетов TCP в C #, который я сделал с помощью оболочек TcpListener / TcpClient для Socket. Я довольно плохо знаком с сетью в целом, поэтому я не знал, как TCP обрабатывает отправленные данные и как он не сохраняет границы сообщений. После небольшого исследования я думаю, что я нашел твердое решение, но мне интересно, есть ли у кого-нибудь еще советы для меня.

В настоящее время данные, которые я отправляю, являются байтом [] сериализованного объекта класса с использованием protobuf (библиотека обмена данными Google)https://code.google.com/p/protobuf/

После того, как я сериализовал свои данные и перед их отправкой, я решил добавить 4-байтовый Int32 в начале байтового массива. Моя идея состоит в том, что когда пакет отправляется на сервер, он анализирует Int32 и затем ждет, пока не получит это число байтов, прежде чем что-либо делать с данными, в противном случае просто снова вызову BeginRead.

Вот код, через который он проходил до того, как я записал данные, и он, кажется, работает нормально, но я открыт для любых предложений по производительности:

public byte[] PackByteArrayForSending(byte[] data)
{
    // [0-3] Packet Length 
    // [3-*] original data

    // Get Int32 of the packet length
    byte[] packetLength = BitConverter.GetBytes(data.Length);
    // Allocate a new byte[] destination array the size of the original data length plus the packet length array size
    byte[] dest = new byte[packetLength.Length + data.Length];

    // Copy the packetLength array to the dest array
    Buffer.BlockCopy(packetLength, 0, dest, 0, packetLength.Length);
    // Copy the data array to the dest array
    Buffer.BlockCopy(data, 0, dest, packetLength.Length, data.Length);

    return dest;
}

Я немного застрял на стороне сервера. Я читал переменную packetLength, используя Buffer.BlockCopy для копирования первых 4 байтов, а затем BitConverter.ToInt32 для считывания длины, которую я должен получить. Я не уверен, должен ли я постоянно читать входящие данные в специфичный для клиента объект Stream или просто использовать цикл while. Вот пример кода, который у меня есть на стороне сервера:

NetworkStream networkStream = client.NetworkStream;
int bytesRead = networkStream.EndRead(ar);

if (bytesRead == 0)
{
  Console.WriteLine("Got 0 bytes from {0}, marking as OFFLINE.", client.User.Username);
  RemoveClient(client);
}

Console.WriteLine("Received {0} bytes.", bytesRead);

// Allocate a new byte array the size of the data that needs to be deseralized.
byte[] data = new byte[bytesRead];

// Copy the byte array into the toDeserialize buffer
Buffer.BlockCopy(
  client.Buffer,
  0,
  data,
  0,
  bytesRead);

// Read the first Int32 tp get the packet length and then use the byte[4] to get the packetLength
byte[] packetLengthBytes = new byte[4];
Buffer.BlockCopy(
  data,
  0,
  packetLengthBytes,
  0,
  packetLengthBytes.Length);

int packetLength = BitConverter.ToInt32(packetLengthBytes, 0);

// Now what do you recommend?

// If not all data is received, call 
// networkStream.BeginRead(client.Buffer, 0, client.Buffer.Length, ReadCallback, client);
// and preserve the initial data in the client object

Спасибо за ваше время и советы, я с нетерпением жду, чтобы узнать больше об этом предмете.

Ответы на вопрос(1)

Ваш ответ на вопрос