2010-09-10 122 views
2

我使用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

回答

3

這樣做的最典型的方法是沿着具有數據塊的前幾個字節的東西線是塊長度。例如,如果你的對象大小總是小於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

3

你正在處理的典型UDP數據包大小限制爲64k或65535字節。分配一個64k字節的數組並將其傳遞給Receive()函數。假設典型的套接字實現,Receive()函數將返回實際接收的字節數。