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

发布于 2024-09-18 06:25:51 字数 700 浏览 4 评论 0原文

我使用 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);
        }

i use a UDP-socket for sending/receiving objects.
I serialize the objects into a byte array send it and receive it with a client.
But before i can receive i have to allocate a byte array. I must do it before and then handle the Socket.Receive()-methode the array.
But my objects have a variable length. How can i discover the array-size?

Thank you

Edit: Here a example of my receive-methode:

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

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(2

如果没结果 2024-09-25 06:25:51

执行此操作的最典型方法涉及将数据块的前几个字节作为块长度。

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

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

编辑:

自从我在.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
      }
   }
}

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

The most typical method of doing this involves something along the lines of having the first few bytes of a data chunk be the chunk length.

So, for example, if your object size is always under 65k or there abouts, you could send the array size through the socket first as a short (Look at using the BitConverter class). The receiver would read the first chunk it receives into a buffer (probably one roughly the size of a nominal UDP packet, somewhere around 512 bytes), grab the first two bytes, convert them to a short, and set up the buffer for the object. It would then continue to read from the socket until that buffer is full, and pass that buffer off to the de-serializer.

This of course doesn't cover error handing and such, but it's the basic idea.

EDIT:

It's been awhile since I did anything with UDP in .Net, but something like this might work (In somewhat 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
      }
   }
}

That's the basic process, ignoring locking due to multiple threads (which you will have to deal with since Receive bocks), and reading and writing from different spots in the memory stream. Hopefully this is enough to get you going in the right direction.

萌酱 2024-09-25 06:25:51

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

Chances are you're dealing with typical UDP packets which are limited to a size of 64k, or 65535 bytes. Allocate a 64k-byte array and pass that to the Receive() function. Assuming a typical socket implementation, the Receive() function will return the number of bytes that were actually received.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文