Description
Background and motivation
This is subset from #30797. There is long discussion about how to make sending and receiving UDP more efficient. Current overloads allocate a lot for each packet and that kills performance and it puts lot of pressure on GC. Garbage collection has significant impact on scenarios that are sensitive to timing - like multiplayer Unity games.
API Proposal
namespace System.Net.Sockets;
public class Socket
{
+ public int ReceiveFrom(Span<byte> buffer, SocketFlags socketFlags, SocketAddress socketAddress);
+ public ValueTask<int> ReceiveFromAsync(Memory<byte> buffer, SocketFlags socketFlags, SocketAddress socketAddress, CancellationToken cancellationToken = default);
+. public int SendTo(ReadOnlySpan<byte> buffer, SocketFlags socketFlags, SocketAddress socketAddress);
+. public ValueTask<int> SendToAsync(ReadOnlyMemory<byte> buffer, SocketFlags socketFlags, SocketAddress socketAddress, CancellationToken cancellationToken = default);
}
Instead of allocating and returning EndPoint, we can reuse SocketAddress
and we would update it in place. Ideally using API proposed in #86872 but in worst case the SocketAddress
is already writable and we can play some internal tricks.
API Usage
example of simple server that would process request - inspired by DNS server linked in #30797
SocketAddress sa = new SocketAddress(AddressFamily.InterNetworkV6);
while (doWork)
{
int receivedLength = s.ReceiveFrom(buffer, SocketFlags.None, sa);
response = processRequest(buffer.Slice(0, receivedLength);
s.SendTo(response, SocketFlags.None, sa);
}
The async version would be basically same with addition of CancellationToken
. Unlike ReceiveFromAsync
that used EndPoint
and returns SocketReceiveFromResult
we would return ValueTask<int>
just like the synchronous version and we would update socketAddress
in-place.
Alternative Designs
No response
Risks
This is low-level API intended for experienced users. While there is nothing particularly dangerous one should be very careful about life cycle of the socketAddress
as it can be overwritten on subsequent use.