I'm struggling to understand what's happening in this two scenarios:
I have a udpClient that sends messages to a remote host. I create the client and then call the Send() method specifying the remote host to which send the data.
I have a udpClient that sends messages to a remote host. I create the client and call the Connect() method to avoid to specify the remote host to which send the data in the Send() method, indeed from the documentation: "The Connect method establishes a default remote host using the value specified in the endPoint parameter. Once established, you do not have to specify a remote host in each call to the Send method."
The udpClient is created in the same way:
private static UdpClient CreateUdpClient(IPAddress localNetworkAdapter, IPEndPoint addressForReadingData)
{
var client = new UdpClient();
client.Client.ExclusiveAddressUse = false;
client.Client.SetSocketOption(SocketOptionLevel.Socket, SocketOptionName.ReuseAddress, true);
client.Client.Blocking = false;
client.Client.Ttl = 10;
client.Client.SetSocketOption(SocketOptionLevel.IP, SocketOptionName.MulticastTimeToLive, 10);
client.Client.Bind(new IPEndPoint(localNetworkAdapter, 0));
client.Connect(addressForReadingData);
return client;
}
Everything works fine but if I cut the network connectivity and then reconnect the network:
In the first scenario everything works fine.
in the second one a SocketException (10022 - An invalid argument was supplied) is thrown every time the Send() method is called.
Since the UDP protocol is connectionless and the Connect() method provides just a way to not specify the remote host in each Send() call, I'm wondering what the difference between this two scenarios. In order to let the the second scenario works I have to close the client and then recreate/reconnect it.
I wrote a simple test code to prove this behavior, just change the scenario
variable to change between the two scenarios.
- If
scenario == false
the console print an error message as long as the connectivity is down but will start to print "Sent" when the connectivity comes back - If
scenario == true
you will see error messages keep going to be printed even if the connectivity came back
using System.Net;
using System.Net.Sockets;
namespace UdpTester
{
static class Program
{
static void Main(string[] args)
{
// scenario 1 -> false
// scenario 2 -> true
bool scenario = true;
IPEndPoint remoteHost = new IPEndPoint(IPAddress.Parse("172.30.65.8"), 3000);
IPAddress localNetworkAdapter = IPAddress.Parse("172.30.65.3");
ushort udpMaxPacketSizeInBytes = 1400;
Console.WriteLine("Starting UDP tester:");
Console.WriteLine($"Remote host: {remoteHost}");
Console.WriteLine($"Network adapter: {localNetworkAdapter}");
Console.WriteLine($"Max packet size (Bytes): {udpMaxPacketSizeInBytes}");
var udpClient = CreateClient(localNetworkAdapter, remoteHost, udpMaxPacketSizeInBytes, scenario);
SendData(udpClient, remoteHost, scenario);
}
static UdpClient CreateClient(IPAddress localNetworkAdapter, IPEndPoint remoteHost, int bufferSize, bool scenario)
{
var client = new UdpClient();
client.Client.ExclusiveAddressUse = false;
client.Client.SetSocketOption(SocketOptionLevel.Socket, SocketOptionName.ReuseAddress, true);
client.Client.SendBufferSize = bufferSize;
client.Client.Blocking = false;
client.Client.Ttl = 10;
client.Client.SetSocketOption(SocketOptionLevel.IP, SocketOptionName.MulticastTimeToLive, 10);
client.Client.Bind(new IPEndPoint(localNetworkAdapter, 0));
if(scenario)
client.Connect(remoteHost);
return client;
}
static void SendData(UdpClient client, IPEndPoint remoteHost, bool scenario)
{
Console.WriteLine("\nSending data...");
while (true)
{
try
{
if(scenario)
client.Send(new byte[1], 1);
else
client.Send(new byte[1], 1, remoteHost);
Thread.Sleep(500);
Console.WriteLine("Sent");
}
catch (Exception ex)
{
Console.WriteLine(ex);
}
}
}
}
}
Thanks for the help,
Regards