C#:UDP Socket - 接收未知大小的数据

时间:2010-09-10 18:17:53

标签: arrays sockets xna udp byte

我使用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 个答案:

答案 0 :(得分:3)

最常见的方法是将数据块的前几个字节作为块长度。

因此,例如,如果您的对象大小始终低于65k或大约,您可以首先通过套接字发送数组大小作为简短(使用BitConverter类查看)。接收器将其接收到的第一个块读入缓冲区(可能大约是标称UDP数据包的大小,大约512字节),获取前两个字节,将它们转换为short,并为对象设置缓冲区。然后它将继续从套接字读取,直到缓冲区已满,并将该缓冲区传递给反序列化器。

这当然不包括错误处理等,但这是基本的想法。

编辑:

自从我在.Net中使用UDP做了一些事情以来,已经有一段时间了,但是这样的事情可能会起作用(在某种程度上的伪代码中)

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
      }
   }
}

这是基本过程,忽略了由于多个线程(自接收块以来你必须处理)的锁定,以及从内存流中的不同位置读取和写入。希望这足以让你朝着正确的方向前进。

答案 1 :(得分:3)

您可能正在处理典型的UDP数据包,其大小限制为64k或65535字节。分配一个64k字节的数组并将其传递给Receive()函数。假设一个典型的套接字实现,Receive()函数将返回实际接收的字节数。