ARTICLE AD BOX
Here's my code in my listener function.
while (!stoppingToken.IsCancellationRequested) { try { if (_udpClient == null) { // Explicit binding to match DDPHelper robustness var localEP = new IPEndPoint(IPAddress.Any, ListenPort); var socket = new Socket(AddressFamily.InterNetwork, SocketType.Dgram, ProtocolType.Udp); socket.SetSocketOption(SocketOptionLevel.Socket, SocketOptionName.ReuseAddress, true); // CRITICAL: Increase receive buffer size for high-frequency UDP on macOS // Default macOS buffer may be too small, causing packet delays/drops socket.SetSocketOption(SocketOptionLevel.Socket, SocketOptionName.ReceiveBuffer, 96); // 256KB socket.Bind(localEP); _udpClient = new UdpClient { Client = socket }; // Log actual buffer size (OS may override our request) var actualBufferSize = (int)socket.GetSocketOption(SocketOptionLevel.Socket, SocketOptionName.ReceiveBuffer)!; Console.WriteLine($"UDP Service: Bound successfully. Receive buffer: {actualBufferSize} bytes"); _fpsWatch.Start(); } // 2. Processing Loop - CRITICAL: Use synchronous receive to prevent macOS kernel batching while (!stoppingToken.IsCancellationRequested && _udpClient != null) { try { // CRITICAL FIX: Synchronous Receive() instead of ReceiveAsync() // macOS batches async UDP receives at kernel level, causing jerky delivery if (_udpClient.Available > 0) { IPEndPoint remoteEP = new IPEndPoint(IPAddress.Any, 0); byte[] buffer = _udpClient.Receive(ref remoteEP); if (buffer.Length == 96) { LastFrame = buffer; _frameCount++; // Log FPS every 60 frames to diagnose UDP receive rate if (_frameCount % 60 == 0) { double fps = _frameCount / _fpsWatch.Elapsed.TotalSeconds; Console.WriteLine($"UDP Receive FPS: {fps:F1} ({_frameCount} frames in {_fpsWatch.Elapsed.TotalSeconds:F1}s)"); } // Send directly to WebSocket clients - no throttling MusicDongleWebSocketHandler.BroadcastFrame(buffer); } } else { // No data available, yield to prevent busy-waiting await Task.Delay(1, stoppingToken); } } catch (OperationCanceledException) { break; // Stopping } catch (SocketException sex) { Console.WriteLine($"UDP Socket Error: {sex.Message}. Reinitializing..."); _udpClient?.Dispose(); _udpClient = null; break; // Break info loop to re-bind } catch (Exception ex) { Console.WriteLine($"UDP Packet Error: {ex.Message}"); await Task.Delay(100, stoppingToken); } } } catch (Exception ex) { Console.WriteLine($"UDP Bind/Outer Error: {ex.Message}. Retrying in 5s..."); _udpClient?.Dispose(); _udpClient = null; // Wait before retrying bind await Task.Delay(5000, stoppingToken); } } Console.WriteLine("UDP Service: Stopping..."); _udpClient?.Dispose(); }If i run this function on windows, I am receiving the packets at 30fps no problem.
If i run this function on macos, it appears to be buffering somehow. My packets are 96 bytes of data, always, and come at 30fps and I have been unable to get it to not drop frames. I have tried plenty of things including making it synchronous instead of async, and I've also tested it with a complete rewrite to do it old-style where every received frame sets up a new event.
I need someone to give me some insight on how to force the buffer to give me my data on command.
