UdpClient doesn't receive data with ReceiveAsync but does with BeginReceive
Hello all, I'm making a torrent client and I'm facing a problem
4
Replies
I have 2 versions of a
ReceiveAsync:
ExecuteUDPRequest
method, 1 using BeginReceive to receive and one using ReceiveAsync, the
ReceiveAsync
hangs, it doesn't crash or anything, just hangs.
BeginReceive:
private async Task<byte[]?> ExecuteUdpRequest(Uri uri, byte[] message)
{
if (uri == null) throw new ArgumentNullException(nameof(uri));
if (message == null) throw new ArgumentNullException(nameof(message));
byte[]? data = null;
IPEndPoint any = new(IPAddress.Any, ListenPort);
try
{
using (UdpClient udpClient = new UdpClient())
{
udpClient.Client.SendTimeout = (int)TimeSpan.FromSeconds(5).TotalMilliseconds;
udpClient.Client.ReceiveTimeout = (int)TimeSpan.FromSeconds(15).TotalMilliseconds;
Logger.Log($"sending message to {uri.Host}, returning.", source: "UdpRequest");
int numBytesSent = await udpClient.SendAsync(message, message.Length, uri.Host, uri.Port);
Logger.Log($"Sent: {numBytesSent}", source: "UdpRequest");
var res = udpClient.BeginReceive(null, null);
//data = udpClient.EndReceive(res, ref any);
// begin recieve right after request
if (res.AsyncWaitHandle.WaitOne(TimeSpan.FromSeconds(5)))
{
Logger.Log($"Recieved message from endpoint, returning.", source: "UdpRequest");
#pragma warning disable CS8600 // Converting null literal or possible null value to non-nullable type.
data = udpClient.EndReceive(res, ref any);
#pragma warning restore CS8600 // Converting null literal or possible null value to non-nullable type.
}
else
{
Logger.Log($"No Bytes Recieved from UdpRequest", source: "UdpRequest");
// here the client just times out.
}
}
}
catch(SocketException ex)
{
Logger.Log($"Failed UDP tracker message to {uri} for torrent {Torrent.InfoHash}: {ex.Message}");
}
return data;
}
}
private async Task<byte[]?> ExecuteUdpRequest2(Uri uri, byte[] message)
{
byte[]? data = null;
if (uri == null) throw new ArgumentNullException(nameof(uri));
if (message == null) throw new ArgumentNullException(nameof(message));
int port = await Torrent.PortList.AwaitOpenPort();
IPEndPoint ep = new IPEndPoint(IPAddress.Any, port);
try
{
using UdpClient udpClient = new(ep);
Logger.Log($"Listening on : {ep}");
udpClient.Client.SendTimeout = (int)TimeSpan.FromSeconds(5).TotalMilliseconds;
udpClient.Client.ReceiveTimeout = (int)TimeSpan.FromSeconds(5).TotalMilliseconds;
Logger.Log($"sending message to {uri.Host}, returning.", source: "UdpRequest");
int numBytesSent = await udpClient.SendAsync(message, message.Length, uri.Host, uri.Port);
Logger.Log($"Sent: {numBytesSent}", source: "UdpRequest");
UdpReceiveResult? res;
//var res = udpClient.BeginReceive(null, null);
try
{
CancellationTokenSource cts = new CancellationTokenSource();
var timer = new Timer(state => cts.Cancel(), null, 5000, Timeout.Infinite);
res = await udpClient.ReceiveAsync(cts.Token);
}
catch (OperationCanceledException ex)
{
res = null;
}
// begin recieve right after request
if (res != null && res?.Buffer != null && res?.Buffer.Length > 0)
{
Logger.Log($"Recieved message from endpoint, returning.", source: "UdpRequest");
data = res?.Buffer;
}
else
{
Logger.Log($"No Bytes Recieved from UdpRequest", source: "UdpRequest");
// here the client just times out.
}
}
catch (SocketException ex)
{
Logger.Log($"Failed UDP tracker message to {uri} for torrent {Torrent.InfoHash}: {ex.Message}");
}
Torrent.PortList.SetPortUnused(port);
return data;
}
ReceiveAsync
does not respect my Cancellation Token, it just hangs forever.
no exceptions thrown either
I find it particularly weird that
ReceiveAsync
does not take in an endpoint as a parameter like
BeginReceive
does but there is no overload where it takes such a parameter