/// <summary> /// Instantiates a UDP Broadcast client /// </summary> /// <param name="address">The IPAddress which the socket should be bound to</param> /// <param name="port">The port used by the endpoint that should different than 0 on a Subscriber context</param> /// <param name="pubSubContext">The context in which the UDP client is to be used </param> public UdpClientBroadcast(IPAddress address, int port, UsedInContext pubSubContext) { Address = address; Port = port; PubSubContext = pubSubContext; CustomizeSocketToBroadcastThroughIf(); IPEndPoint boundEndpoint = null; if (!RuntimeInformation.IsOSPlatform(OSPlatform.Linux) || pubSubContext == UsedInContext.Publisher) { //Running on Windows or Publisher on Windows/Linux boundEndpoint = new IPEndPoint(address, port); } else { //Running on Linux and Subscriber // On Linux must bind to IPAddress.Any on receiving side to get Broadcast messages boundEndpoint = new IPEndPoint(IPAddress.Any, port); } Client.Bind(boundEndpoint); EnableBroadcast = true; Utils.Trace("UdpClientBroadcast was created for address: {0}:{1} - {2}.", address, port, pubSubContext); }
/// <summary> /// Create specific <see cref="UdpClient"/> for specified <see cref="NetworkInterface"/> and <see cref="IPEndPoint"/>. /// </summary> /// <param name="pubSubContext">Is the method called in a publisher context or a subscriber context</param> /// <param name="networkInterface"></param> /// <param name="configuredEndpoint"></param> /// <returns></returns> private static UdpClient CreateUdpClientForNetworkInterface(UsedInContext pubSubContext, NetworkInterface networkInterface, IPEndPoint configuredEndpoint) { UdpClient udpClient = null; IPInterfaceProperties ipProps = networkInterface.GetIPProperties(); IPAddress localAddress = IPAddress.Any; foreach (var address in ipProps.UnicastAddresses) { if (address.Address.AddressFamily == AddressFamily.InterNetwork) { localAddress = address.Address; } } try { //detect the port used for binding int port = 0; if (pubSubContext == UsedInContext.Subscriber) { port = configuredEndpoint.Port; } if (IsIPv4MulticastAddress(configuredEndpoint.Address)) { //instantiate multi-cast UdpClient udpClient = new UdpClientMulticast(localAddress, configuredEndpoint.Address, port); } else if (IsIPv4BroadcastAddress(configuredEndpoint.Address, networkInterface)) { //instantiate broadcast UdpClient depending on publisher/subscriber usage context udpClient = new UdpClientBroadcast(localAddress, port, pubSubContext); } else { //instantiate unicast UdpClient depending on publisher/subscriber usage context udpClient = new UdpClientUnicast(localAddress, port); } if (pubSubContext == UsedInContext.Publisher) { //try to send 1 byte for target IP udpClient.Send(new byte[] { 0 }, 1, configuredEndpoint); } // On Windows Only since Linux does not support this if (!RuntimeInformation.IsOSPlatform(OSPlatform.Linux)) { // Disable exceptions raised by ICMP Port Unreachable messages udpClient.Client.IOControl((IOControlCode)SIO_UDP_CONNRESET, new byte[] { 0, 0, 0, 0 }, null); } } catch (Exception ex) { Utils.Trace(Utils.TraceMasks.Information, "Cannot use Network interface '{0}'. Exception: {1}", networkInterface.Name, ex.Message); if (udpClient != null) { //cleanup udpClient.Dispose(); udpClient = null; } } return(udpClient); }
/// <summary> /// Creates and returns a list of <see cref="UdpClient"/> created based on configuration options /// </summary> /// <param name="pubSubContext">Is the method called in a publisher context or a subscriber context</param> /// <param name="networkAddressUrl">The configuration object <see cref="NetworkAddressUrlDataType"/>.</param> /// <param name="configuredEndpoint">The configured <see cref="IPEndPoint"/> that will be used for data exchange.</param> /// <returns></returns> internal static List <UdpClient> GetUdpClients(UsedInContext pubSubContext, NetworkAddressUrlDataType networkAddressUrl, IPEndPoint configuredEndpoint) { StringBuilder buffer = new StringBuilder(); buffer.AppendFormat("networkAddressUrl.NetworkInterface = {0} \n", networkAddressUrl != null ? networkAddressUrl.NetworkInterface : "null"); buffer.AppendFormat("networkAddressUrl.Url = {0} \n", networkAddressUrl?.Url != null ? networkAddressUrl?.Url : "null"); buffer.AppendFormat("configuredEndpoint = {0}", configuredEndpoint != null ? configuredEndpoint.ToString() : "null"); Utils.Trace(Utils.TraceMasks.Information, buffer.ToString()); List <UdpClient> udpClients = new List <UdpClient>(); //validate input parameters if (networkAddressUrl == null || configuredEndpoint == null) { //log warning? return(udpClients); } //detect the list on network interfaces that will be used for creating the UdpClient s List <NetworkInterface> usableNetworkInterfaces = new List <NetworkInterface>(); var interfaces = NetworkInterface.GetAllNetworkInterfaces(); if (string.IsNullOrEmpty(networkAddressUrl.NetworkInterface)) { Utils.Trace(Utils.TraceMasks.Information, "No NetworkInterface name was provided. Use all available NICs."); usableNetworkInterfaces.AddRange(interfaces); } else { //the configuration contains a NetworkInterface name, try to locate it foreach (NetworkInterface nic in interfaces) { if (nic.Name.Equals(networkAddressUrl.NetworkInterface, StringComparison.OrdinalIgnoreCase)) { usableNetworkInterfaces.Add(nic); } } if (usableNetworkInterfaces.Count == 0) { Utils.Trace(Utils.TraceMasks.Information, "The configured value for NetworkInterface name('{0}') could not be used.", networkAddressUrl.NetworkInterface); usableNetworkInterfaces.AddRange(interfaces); } } foreach (NetworkInterface nic in usableNetworkInterfaces) { Utils.Trace(Utils.TraceMasks.Information, "NetworkInterface name('{0}') attempts to create instance of UdpClient.", nic.Name); //ignore loop-back interface if (nic.NetworkInterfaceType == NetworkInterfaceType.Loopback) { continue; } //ignore tunnel interface if (nic.NetworkInterfaceType == NetworkInterfaceType.Tunnel) { continue; } UdpClient udpClient = CreateUdpClientForNetworkInterface(pubSubContext, nic, configuredEndpoint); if (udpClient == null) { continue; } //store UdpClient udpClients.Add(udpClient); Utils.Trace(Utils.TraceMasks.Information, "NetworkInterface name('{0}') UdpClient successfully created.", nic.Name); } return(udpClients); }