title: Why is Socket.BeginReceive losing packets from UDP?
body: <p>The following code waits for data over UDP. I have a test function that sends 1000 packets (datagrams?) of 500 bytes each. Each time I run the test function, the receiver gets only the first few dozen packets but drops the rest. I looked at the incoming network data using Wireshark and I see all 1000 packets are actually received, but just don't make it to may app's code.</p>
  
  <p>Here is some of the relevant VB.NET 3.5 code:</p>
  
  <pre><code>Private _UdbBuffer As Byte()
  Private _ReceiveSocket As Socket
  Private _NumReceived As Integer = 0
  Private _StopWaitHandle As AutoResetEvent
  
  Private Sub UdpListen()
      _StopWaitHandle = New AutoResetEvent(False)
      _UdpEndPoint = New Net.IPEndPoint(Net.IPAddress.Any, UDP_PORT_NUM)
  
      _ReceiveSocket = New Socket(AddressFamily.InterNetwork, SocketType.Dgram, ProtocolType.Udp)
      _ReceiveSocket.Bind(_UdpEndPoint)
  
      ReDim _UdbBuffer(10000)
  
      While Not _StopRequested
          Dim ir As IAsyncResult = _ReceiveSocket.BeginReceive(_UdbBuffer, 0, 10000, SocketFlags.None, AddressOf UdpReceive, Nothing)
  
          If Not _StopRequested Then
              Dim waitHandles() As WaitHandle = {_StopWaitHandle, ir.AsyncWaitHandle}
              If (WaitHandle.WaitAny(waitHandles) = 0) Then
                  Exit While
              End If
          End If
      End While
  
      _ReceiveSocket.Close()
  End Sub
  
  Private Sub UdpReceive(ByVal ar As IAsyncResult)
      Dim len As Integer
      If ar.IsCompleted Then
          len = _ReceiveSocket.EndReceive(ar)
          Threading.Interlocked.Increment(_NumReceived)
          RaiseStatus("Got " &amp; _NumReceived &amp; " packets")
      End If
  End Sub
  </code></pre>
  
  <p>I am sending the data as follows (not worried about the packet content for now):</p>
  
  <pre><code>For i as UShort = 0 to 999
     Dim b(500) as Byte
     _UdpClient.Send(b, b.Length)       
  Next
  </code></pre>
  
  <p>If I add a small delay after each call to Send, more packets make it through; however since Wireshark says that they were all received anyways, it seems that the problem is in my receive code. I should mention that UdpListen is running on a separate thread.</p>
  
  <p>Any idea why I am dropping packets? I also tried UdpClient.BeginReceive/EndReceive but had the same problem. </p>
  
  <p>A second issue that bothers me is the global nature of the receive buffer when using Sockets and I am not sure if I don't process incoming packets quickly enough that the buffer will be overwritten. Not sure what to do about that just yet but I am open to suggestions.</p>
  
  <p><strong>Sep 26: Update</strong></p>
  
  <hr>
  
  <p>Based on the various, somewhat conflicting suggestions from replies to this and other posts, I made some changes to my code. Thanks to all who chimed in various bits; I now get all my packets from dial-up to Fast Ethernet. As you can see, it was my code at fault and not the fact that UDP drops packets (in fact I have not seen more than a tiny percentage of packets being dropped or out of order since my fixes). </p>
  
  <p>Differences: </p>
  
  <p>1) Replaced BeginReceive()/EndReceive() with BeginReceiveFrom()/EndReceiveFrom(). By itself this had no notible effect though.</p>
  
  <p>2) Chaining BeginReceiveFrom() calls instead of waiting for the async handle to set. Not sure if any benefit here.</p>
  
  <p>3) Explicitly set the Socket.ReceiveBufferSize to 500000 which is enough for 1 second worth of my data at Fast Ethernet speed. Turns out this is a different buffer than the one passed to BeginReceiveFrom(). This had the biggest benefit.</p>
  
  <p>4) I also modified my send routine to wait a couple of ms after having sent a certain number of bytes to throttle based on expected bandwidth. This had a big benefit for my receiving code even though Wireshark said all my data still made it across even without this delay.</p>
  
  <p>I did NOT end up using a separate processing thread because, as I understand it, each call to BeginReceiveFrom will invoke my callback on a new worker thread. This means that I can have more than one callback running at the same time. It also means that once I call BeginReceiveFrom I have time to do my stuff (as long as I don't take too long and exaust the available worker threads).</p>
  
  <pre><code>Private Sub StartUdpListen()
      _UdpEndPoint = New Net.IPEndPoint(Net.IPAddress.Any, UDP_PORT_NUM)
      _ReceiveSocket = New Socket(AddressFamily.InterNetwork, SocketType.Dgram, ProtocolType.Udp)
      _ReceiveSocket.ReceiveBufferSize = 500000
      _ReceiveSocket.Bind(_UdpEndPoint)
  
      ReDim _Buffer(50000)
  
      _ReceiveSocket.BeginReceiveFrom(_Buffer, 0, _Buffer.Length, SocketFlags.None, _UdpEndPoint, AddressOf UdpReceive, Nothing)
  
  End Sub
  
  Private Sub UdpReceive(ByVal ar As IAsyncResult)
      Dim len As Integer = _ReceiveSocket.EndReceiveFrom(ar, _UdpEndPoint)
      Threading.Interlocked.Increment(udpreceived)
  
      Dim receiveBytes As Byte()
      ReDim receiveBytes(len - 1)
      System.Buffer.BlockCopy(_Buffer, 0, receiveBytes, 0, len)
  
      _ReceiveSocket.BeginReceiveFrom(_Buffer, 0, _UdbBuffer.Length, SocketFlags.None, _UdpEndPoint, AddressOf UdpReceive, Nothing)
  
      //' At this point, do what we need to do with the data in the receiveBytes buffer
      Trace.WriteLine("count=" &amp; udpreceived)
  End Sub
  </code></pre>
  
  <p>What is not shown above is the error handling and dealing with UDP data being out of order or missing.</p>
  
  <p>I think this handles my issue, but if anybody still sees anything wrong with the above (or something I could do better) I would love to hear about it.</p>