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

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

问题描述:

我使用UDP套接字发送/接收对象。 我将这些对象序列化为一个字节数组发送它并用客户端接收它。 但在我可以收到之前,我必须分配一个字节数组。我必须先完成它,然后处理Socket.Receive() - 方法数组。 但我的对象有一个可变长度。我怎样才能发现数组大小?C#:UDP套接字 - 接收未知大小的数据

谢谢

编辑:我收到-梅索德的下面一个例子:

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

ReceiveFrom不返回收到的字节数? – 2010-12-30 08:07:51

这样做的最典型的方法是沿着具有数据块的前几个字节的东西线是块长度。例如,如果你的对象大小总是小于65k或者大约在那里,你可以首先通过套接字发送数组大小作为一个short(请看使用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 
     } 
    } 
} 

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

+0

我怎样才能抓住前两个字节?我只能一口气从插座读取数据。如果缓冲区不够大,我会得到一个异常。看起来像udp-sockets这个问题是正常的^^ – user437899 2010-09-10 19:07:54

+2

这种方法只适用于面向连接的套接字(例如TCP),而不是无连接的套接字(例如UDP)。我无法与XNA交谈。但在.NET中,如果消息比缓冲区大,缓冲区将被消息的第一部分填充,消息的其余部分将丢失,并抛出一个'SocketException'。你将不得不一次读取整个消息,这需要一个足够大的缓冲区来容纳你可能收到的最大消息。 – 2010-09-10 19:25:04

+0

好的,我明白你的接受。但是有一个小问题。它看起来像将.Receive() - Methode的结果放在流中,但是这个结果不是对象/字节,结果是一个Int(接收到的字节)。那是内涵吗?你用.Receive-Method处理的方式是这样的:byte [] objData = new byte [bufferSize]; udpSocket.ReceiveFrom(objData,ref ep);我会把这个例子放在我的问题中。 – user437899 2010-09-10 20:00:00

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