C #: UDP Socket - получение данных с неизвестным размером - PullRequest
2 голосов
/ 10 сентября 2010

Я использую UDP-сокет для отправки / получения объектов.Я сериализирую объекты в байтовый массив, отправляю его и получаю с клиентом.Но прежде чем я могу получить, я должен выделить массив байтов.Я должен сделать это раньше, а затем обработать Socket.Receive () - метод массива.Но мои объекты имеют переменную длину.Как узнать размер массива?

Спасибо

Редактировать: Вот пример моего метода получения:

BinaryFormatter bf = new BinaryFormatter();

public Object ReceiveUdpPacket()
        {
            byte[] objData = new byte[bufferSize];

            IPEndPoint ipep = new IPEndPoint(IPAddress.Any, 0);
            EndPoint ep = (EndPoint)ipep;
            MemoryStream ms = new MemoryStream();

            udpSocket.ReceiveFrom(objData, ref ep);

            ms.Write(objData, 0, objData.Length);
            ms.Seek(0, SeekOrigin.Begin);

            return (Object)bf.Deserialize(ms);
        }

Ответы [ 2 ]

3 голосов
/ 10 сентября 2010

Скорее всего, вы имеете дело с типичными пакетами UDP, размер которых не превышает 64 Кб или 65535 байт. Выделите 64-байтовый массив и передайте его функции Receive(). Предполагая типичную реализацию сокета, функция Receive() будет возвращать количество байтов, которые были фактически получены.

3 голосов
/ 10 сентября 2010

Наиболее типичный способ сделать это состоит в том, чтобы первые несколько байтов блока данных были длиной фрагмента.

Так, например, если размер вашего объекта всегда меньше 65k илитам вы можете отправить размер массива через сокет первым как короткий (посмотрите на использование класса BitConverter).Получатель считывает первый полученный блок в буфер (вероятно, примерно размером с номинальный пакет UDP, где-то около 512 байт), захватывает первые два байта, преобразует их в короткий и устанавливает буфер для объекта.,Затем он продолжит чтение из сокета, пока этот буфер не заполнится, и передаст этот буфер десериализатору.

Это, конечно, не распространяется на обработку ошибок и тому подобное, но это основная идея.

РЕДАКТИРОВАТЬ:

Прошло некоторое время, так как я сделал что-то с UDP в .Net, но что-то вроде этого может работать (в несколько psuedocode)

var bigBuffer = new MemoryStream();

//This should be run in a thread
void UdpLoop()
{
   while(!done)
   {
      var buffer = udpClient.Receive();
      bigBuffer.Write(buffer,buffer.Length);
   }
}

void MessageProcessor()
{
   var messageLength = 0;
   while(!done)
   {
      if(bigBuffer.Length > 0 && messageLength == 0)
      {
         var lengthBytes = new byte[2];
         bigBuffer.Read(lengthBytes, 2);
         messageLength = BitConverter.ToInt16(lengthBytes); 
      }
      if(messageLength > 0 && bigBuffer.Length > messageLength)
      {
         var objectBuffer = new byte[messageLength];
         bigBuffer.Read(objectBuffer, messageLength);
         //Do deserialization here
      }
   }
}

Это основнойпроцесс, игнорируя блокировку из-за нескольких потоков (с которыми вам придется иметь дело после получения блоков получения), и чтение и запись из разных мест в потоке памяти.Надеюсь, этого достаточно, чтобы вы пошли в правильном направлении.

...