Why does getting an IP address throw an exception? - c#

Background:
My program starts up and it must obtain the IP address of the machine it is running on.
It is the "server" in a client-server architecture that receives incoming tcp-ip messages.
I should also add the machine :
Has multi-ip addresses available
Is running Windows 2008 R2 Server
Here is the code that obtains the IP address:
public bool IsNetworkAvailable
{
get
{
return System.Net.NetworkInformation.NetworkInterface.GetIsNetworkAvailable();
}
}
public string thisIP { get; private set; }
public void GetThisIP()
{
if (!string.IsNullOrEmpty(thisIP))
{
return;
}
thisIP = "*";
if (IsNetworkAvailable)
{
using (System.Net.Sockets.Socket socket = new System.Net.Sockets.Socket(
System.Net.Sockets.AddressFamily.InterNetwork,
System.Net.Sockets.SocketType.Dgram, 0))
{
socket.Connect("11.0.1.5", 65530);
System.Net.IPEndPoint endPoint = socket.LocalEndPoint as System.Net.IPEndPoint;
thisIP = endPoint.Address.ToString();
}
}
}
Here is the error message:
(0x80004005): A socket operation was attempted to an unreachable network 11.0.1.5:65530
at System.Net.Sockets.Socket.Connect(IPAddress[] addresses, Int32 port)
SOLUTION:
I have changed my code to what rodcesar.santos suggested in this:
Get local IP address
here is my (modified) code (and it works)
System.Net.NetworkInformation.UnicastIPAddressInformation mostSuitableIp = null;
var networkInterfaces = System.Net.NetworkInformation.NetworkInterface.GetAllNetworkInterfaces();
foreach (var network in networkInterfaces)
{
if (network.OperationalStatus != System.Net.NetworkInformation.OperationalStatus.Up)
{
continue;
}
var properties = network.GetIPProperties();
if (properties.GatewayAddresses.Count == 0)
{
continue;
}
if (mostSuitableIp != null)
{
break;
}
foreach (var address in properties.UnicastAddresses)
{
if (address.Address.AddressFamily != System.Net.Sockets.AddressFamily.InterNetwork)
{
continue;
}
if (System.Net.IPAddress.IsLoopback(address.Address))
{
continue;
}
if (mostSuitableIp == null && address.IsDnsEligible)
{
mostSuitableIp = address;
break;
}
}
}
thisIP = mostSuitableIp != null ? mostSuitableIp.Address.ToString() : "";

After reading the accepted answer # A socket operation was attempted to an unreachable host,
I assume that the specific client-computer than receives this error has a somewhat faulty network.
Quoting #Stephen Cleary
This error indicates that the network was not connected or not configured correctly. It is definitely an error on the client machine, not your server.
There isn't much you can do to "solve" the problem. Pretty much all you can do is upgrade the client's network drivers and check for connection problems (maybe they're barely within wireless range, or the Ethernet cable is missing its locking tab).

System.Net.NetworkInformation.UnicastIPAddressInformation mostSuitableIp = null;
var networkInterfaces = System.Net.NetworkInformation.NetworkInterface.GetAllNetworkInterfaces();
foreach (var network in networkInterfaces)
{
if (network.OperationalStatus != System.Net.NetworkInformation.OperationalStatus.Up)
{
continue;
}
var properties = network.GetIPProperties();
if (properties.GatewayAddresses.Count == 0)
{
continue;
}
if (mostSuitableIp != null)
{
break;
}
foreach (var address in properties.UnicastAddresses)
{
if (address.Address.AddressFamily != System.Net.Sockets.AddressFamily.InterNetwork)
{
continue;
}
if (System.Net.IPAddress.IsLoopback(address.Address))
{
continue;
}
if (mostSuitableIp == null && address.IsDnsEligible)
{
mostSuitableIp = address;
break;
}
}
}
thisIP = mostSuitableIp != null ? mostSuitableIp.Address.ToString() : "";

Related

Identify individual Azure app service machines (especially behind a load balancer)

I want to identify individual Azure app service machines so that I can record info in a database. I was thinking I would use the local ip address of the machine using the function below but I get an empty string returned back. The code works for VM's but not for app services. Any thoughts (especially if these are eventually behind a load balancer and running identical code. (any string is ok... it doesn't have to be an ip address)
public static string GetLocalIpAddress()
{
UnicastIPAddressInformation mostSuitableIp = null;
var networkInterfaces = NetworkInterface.GetAllNetworkInterfaces();
foreach (var network in networkInterfaces)
{
if (network.OperationalStatus != OperationalStatus.Up)
continue;
var properties = network.GetIPProperties();
if (properties.GatewayAddresses.Count == 0)
continue;
foreach (var address in properties.UnicastAddresses)
{
if (address.Address.AddressFamily != AddressFamily.InterNetwork)
continue;
if (IPAddress.IsLoopback(address.Address))
continue;
if (!address.IsDnsEligible)
{
if (mostSuitableIp == null)
mostSuitableIp = address;
continue;
}
// The best IP is the IP got from DHCP server
if (address.PrefixOrigin != PrefixOrigin.Dhcp)
{
if (mostSuitableIp == null || !mostSuitableIp.IsDnsEligible)
mostSuitableIp = address;
continue;
}
return address.Address.ToString();
}
}
return mostSuitableIp != null
? mostSuitableIp.Address.ToString()
: "";
}

Remote video stream not displayed every time

I’ m currently debugging a webrtc UWP app, and it is fairly working.
But it happens that the remote stream is not displayed on my MediaElement each time. It’s like the video track is not received although I add it ASAP as recommended. I can’t figure out why it is happening ; is it a code or a network problem ? I grab the stream randomly whatever the network, sometimes successfully, other times not (staying with the same confits).
I use the google STUN servers, and the google webrtc « peer connection server » signaling server on a remote windows server, nothing is installed on my LAN (but my UWP program).
I don’t know what to do to figure out the cause ... any help would be appreciated.
private void Signaller_OnMessageFromPeer(int peerId, string message)
{
Task.Run(async () =>
{
// Debug.Assert(_peerId == peerId || _peerId == -1);
Debug.Assert(message.Length > 0);
if (_peerId != peerId && _peerId != -1)
{
Debug.WriteLine("[Error] Conductor: Received a message from unknown peer while already in a conversation with a different peer.");
return;
}
if (!JsonObject.TryParse(message, out JsonObject jMessage))
{
Debug.WriteLine("[Error] Conductor: Received unknown message." + message);
return;
}
string type = jMessage.ContainsKey(kSessionDescriptionTypeName) ? jMessage.GetNamedString(kSessionDescriptionTypeName) : null;
if (_peerConnection == null)
{
if (!String.IsNullOrEmpty(type))
{
// Create the peer connection only when call is
// about to get initiated. Otherwise ignore the
// messages from peers which could be a result
// of old (but not yet fully closed) connections.
if (type == "offer" || type == "answer")
{
Debug.Assert(_peerId == -1);
_peerId = peerId;
connectToPeerCancelationTokenSource = new CancellationTokenSource();
connectToPeerTask = CreatePeerConnection(connectToPeerCancelationTokenSource.Token);
bool connectResult = await connectToPeerTask;
connectToPeerTask = null;
connectToPeerCancelationTokenSource.Dispose();
if (!connectResult)
{
Debug.WriteLine("[Error] Conductor: Failed to initialize our PeerConnection instance");
await Signaller.SignOut();
return;
}
else if (_peerId != peerId)
{
Debug.WriteLine("[Error] Conductor: Received a message from unknown peer while already in a conversation with a different peer.");
return;
}
}
}
else
{
Debug.WriteLine("[Warn] Conductor: Received an untyped message after closing peer connection.");
return;
}
}
if (!String.IsNullOrEmpty(type))
{
if (type == "offer-loopback")
{
// Loopback not supported
Debug.Assert(false);
}
string sdp = jMessage.ContainsKey(kSessionDescriptionSdpName) ? jMessage.GetNamedString(kSessionDescriptionSdpName) : null;
if (String.IsNullOrEmpty(sdp))
{
Debug.WriteLine("[Error] Conductor: Can't parse received session description message.");
return;
}
RTCSdpType sdpType = RTCSdpType.Offer;
switch (type)
{
case "offer":
sdpType = RTCSdpType.Offer;
break;
case "answer":
sdpType = RTCSdpType.Answer;
break;
case "pranswer":
sdpType = RTCSdpType.Pranswer;
break;
default:
Debug.Assert(false, type);
break;
}
Debug.WriteLine("Conductor: Received session description: " + message + "\r\n" + sdp);
await _peerConnection.SetRemoteDescription(new RTCSessionDescription(sdpType, sdp));
if (sdpType == RTCSdpType.Offer)
{
RTCSessionDescription answer = await _peerConnection.CreateAnswer();
await _peerConnection.SetLocalDescription(answer);
// Send answer
SendSdp(answer);
Debug.WriteLine(String.Format("Conductor: Session Description to be sent : {0}", answer.Sdp));
}
}
else
{
var sdpMid = jMessage.ContainsKey(kCandidateSdpMidName) ? jMessage.GetNamedString(kCandidateSdpMidName) : null;
var sdpMlineIndex = jMessage.ContainsKey(kCandidateSdpMlineIndexName) ? jMessage.GetNamedNumber(kCandidateSdpMlineIndexName) : -1;
var sdp = jMessage.ContainsKey(kCandidateSdpName) ? jMessage.GetNamedString(kCandidateSdpName) : null;
if (String.IsNullOrEmpty(sdpMid) || sdpMlineIndex == -1 || String.IsNullOrEmpty(sdp))
{
Debug.WriteLine("[Error] Conductor: Can't parse received message.\n" + message);
return;
}
var candidate = new RTCIceCandidate(sdp, sdpMid, (ushort)sdpMlineIndex);
await _peerConnection.AddIceCandidate(candidate);
Debug.WriteLine("Conductor: Received candidate : " + message);
}
}).Wait();
}

Determine which network adapter has the highest priority in C#?

If we have multiple network interfaces with the same DNS suffix on a given machine, how do I programatically determine which network interface traffic will be routed over?
For example, I am connected to my companies network via ethernet in office, and connected to the companies network via VPN from inside the office. This sounds stupid, but with the way our networks are connected, if the internal link to our datacenter goes down - I VPN from inside the office to continue development.
Our software has logic to determine our "local ip address" and uses that for authentication logic elsewhere. I know from practice that all my traffic is routed over the VPN when connected - but am struggling with what the correct implementation in code is for robustly choosing the IP address of the adapter with the highest priority.
What I have right now is:
var unicastIpAddressInformation = NetworkInterface.GetAllNetworkInterfaces()
.Where(nic => nic.OperationalStatus == OperationalStatus.Up
&& nic.NetworkInterfaceType != NetworkInterfaceType.Loopback // ...ignore the loopback NIC as we don't want 127.0.0.1 (1 of 2)
&& nic.Name.IndexOf("loopback", StringComparison.OrdinalIgnoreCase) == -1 // ...ignore the loopback NIC as we don't want 127.0.0.1 (2 of 2)
&& nic.Name.IndexOf("virtual", StringComparison.OrdinalIgnoreCase) == -1 // ... ignore virtual NICs so that VMs don't conflict with IP resolution
)
.Select(n => n.GetIPProperties())
// All developer network connections should have the my-company-internal.com suffix
.Where(ipp => ipp.DnsSuffix.ToLowerInvariant().IndexOf("my-company-internal.com", StringComparison.OrdinalIgnoreCase) >= 0)
.Where(ipp => ipp.UnicastAddresses.Any(u => u.Address.AddressFamily == AddressFamily.InterNetwork))
// Is this order by correct?
.OrderByDescending(ipp => ipp.GetIPv4Properties().Index)
.SelectMany(ipp => ipp.UnicastAddresses.Where(ip => ip.Address.AddressFamily == AddressFamily.InterNetwork))
.FirstOrDefault();
I know with the IPV4Properties.Index - it is only populated when IPv4 is enabled; I don't know if corresponds to priority or metric, and whether or not they are guaranteed to be distinct.
I had the same problem here a few weeks ago. I figured out that the NIC priority is persisted in Windows Registry, and there are a few PowerShell scripts that can give you the NIC order, but not the IP addresses. So, I've written the code below and it worked for me. You can use it to see additional info like dns suffix, gateway address and plus.
You just have to call RMSNetUtils.GetTopIpv4Ip(string.Empty)
public class RMSNetUtils
{
private static string _linkagePath = #"SYSTEM\CurrentControlSet\Services\Tcpip\Linkage";
private static string _interfacesPath = #"SYSTEM\CurrentControlSet\Services\Tcpip\Parameters\Interfaces\";
private static List<string> GetBindingsPriority()
{
using (var bindMasterKey = Registry.LocalMachine.OpenSubKey(_linkagePath))
{
var bind = (string[]) bindMasterKey.GetValue("Bind");
var deviceList = bind.Select(x => $#"{_interfacesPath}{x.Replace("\\Device\\", string.Empty)}")
.ToList();
var result = new List<string>();
foreach (var device in deviceList)
{
using (var bindKey = Registry.LocalMachine.OpenSubKey(device))
{
var fixIP = (string[])bindKey.GetValue("IPAddress");
if (fixIP != null)
{
result.Add( fixIP.FirstOrDefault());
continue;
}
var dhcpIp = bindKey.GetValue("DhcpIPAddress");
if (dhcpIp != null)
{
result.Add((string) dhcpIp);
}
}
}
return result;
}
}
private static List<NICInformation> GetFilteredBindings()
{
var bindings = GetBindingsPriority();
var nicsInfo = GetIpList(GetInterNetworkAdapters());
var result = new List<NICInformation>();
foreach (var bind in bindings)
{
var nicInfo = nicsInfo.FirstOrDefault(y => string.Compare(y.IPv4, bind) == 0);
if(nicInfo!= null)
result.Add(nicInfo);
}
return result;
}
private static IEnumerable<IPAddress> GetInterNetworkAdapters()
{
IPHostEntry local = Dns.GetHostEntry(string.Empty);
return (from ipa in local.AddressList
where ipa.AddressFamily == AddressFamily.InterNetwork
select ipa);
}
public static string GetFirstIpv4Ip()
{
return GetFirstIpv4Ip(String.Empty);
}
private static List<NICInformation> GetIpList(IEnumerable<IPAddress> ips)
{
var ipAddresses = ips.Select(x => x.ToString()).ToList();
var result = new List<NICInformation>();
foreach (NetworkInterface ni in NetworkInterface.GetAllNetworkInterfaces())
{
if (ni.NetworkInterfaceType == NetworkInterfaceType.Wireless80211 ||
ni.NetworkInterfaceType == NetworkInterfaceType.Ethernet)
{
foreach (UnicastIPAddressInformation ip in ni.GetIPProperties().UnicastAddresses)
{
if (ip.Address.AddressFamily == AddressFamily.InterNetwork)
{
var ipStr = ip.Address.ToString();
if (ipAddresses.Contains(ipStr))
{
var nic = new NICInformation();
nic.IPv4 = ip.Address.ToString();
nic.Mask = ip.IPv4Mask.ToString();
nic.DnsSuffix = ni.GetIPProperties().DnsSuffix;
var gateway = ni.GetIPProperties().GatewayAddresses.FirstOrDefault();
if(gateway!=null)
nic.Gateway = gateway.Address.ToString();
result.Add(nic);
}
}
}
}
}
return result;
}
public static string GetTopIpv4Ip(string hostName)
{
if (!string.IsNullOrEmpty(hostName))
return GetFirstIpv4Ip(hostName);
var item = GetFilteredBindings().FirstOrDefault();
return item == null ? hostName : item.IPv4;
}
public static string GetFirstIpv4Ip(string hostName)
{
var ip = string.Empty;
try
{
IPHostEntry local = Dns.GetHostEntry(hostName);
var result = GetInterNetworkAdapters().FirstOrDefault();
return result != null ? result.ToString() : hostName;
}
catch (SocketException ex)
{
ip = hostName;
}
return ip;
}
}
public class NICInformation
{
public string DnsSuffix {get;set;}
public string IPv4 {get;set; }
public string Gateway {get;set;}
public string Mask {get;set;}
}

How to obtain Public IP of a device using C# with out using external API/Services

public static string GetPublicIp()
{
HttpContext context = HttpContext.Current;
string ipAddress = context.Request.ServerVariables["HTTP_X_FORWARDED_FOR"];
if (!string.IsNullOrEmpty(ipAddress))
{
string[] addresses = ipAddress.Split(',');
if (addresses.Length != 0)
{
return addresses[0];
}
}
return context.Request.ServerVariables["REMOTE_ADDR"];
}
I'm trying to get the client Public IP but the above code only returns the client Local IP. If different people are connecting to my organisation from the same organisations network, i want to get only their public IP address. I'm not intrested in their local IPs, is this possible.
Below is one solution i have so far seen but i'm NOT liking it.
public static string GetPublicIp()
{
string direction = "";
WebRequest request = WebRequest.Create("http://checkip.dyndns.org");
using (WebResponse response1 = request.GetResponse())
using (StreamReader stream1 = new StreamReader(response1.GetResponseStream()))
{
direction = stream1.ReadToEnd();
}
//Search for the ip in the html
int first1 = direction.IndexOf("Address: ") + 9;
int last1 = direction.LastIndexOf("</body>");
direction = direction.Substring(first1, last1 - first1);
return direction;
}
The above sample solution can get me the public IP but i don't want to be tied to an external service that i have no control over because if that service is down then iam screwed and the performance is terrible.
Does any one know how i can get the clients public IP with out calling external services?
This method gives you the local ip address. I've copied it from a WinRT-Solution, maybe the class names are a bit different in other .NET environments.
private static string GetLocalAddress()
{
var hostnames = NetworkInformation.GetHostNames();
foreach (var hn in hostnames)
{
//IanaInterfaceType == 71 => Wifi
//IanaInterfaceType == 6 => Ethernet (Emulator)
if (hn.IPInformation != null &&
(hn.IPInformation.NetworkAdapter.IanaInterfaceType == 71
|| hn.IPInformation.NetworkAdapter.IanaInterfaceType == 6))
{
return hn.DisplayName;
}
}
return IpAddress.Broadcast.Address;
}
EDIT: The following method prints out all local ip addresses.
private static void PrintLocalAddresses()
{
var interfaces = NetworkInterface.GetAllNetworkInterfaces();
foreach (var ni in interfaces)
{
if (ni.NetworkInterfaceType == NetworkInterfaceType.Ethernet ||
ni.NetworkInterfaceType == NetworkInterfaceType.Wireless80211)
{
var adapterProperties = ni.GetIPProperties();
foreach (var x in adapterProperties.UnicastAddresses)
{
if (x.Address.AddressFamily == AddressFamily.InterNetwork)
{
Console.WriteLine(x.Address);
}
}
}
}
}

In C#, how do I resolve the IP address of a host?

How can you dynamically get the IP address of the server (PC which you want to connect to)?
System.Dns.GetHostEntry can be used to resolve a name to an IP address.
IPHostEntry Host = Dns.GetHostEntry(DNSNameString);
DoSomethingWith(Host.AddressList);
If you Use the Below Method you will be able to resolve correctly
public static bool GetResolvedConnecionIPAddress(string serverNameOrURL, out IPAddress resolvedIPAddress)
{
bool isResolved = false;
IPHostEntry hostEntry = null;
IPAddress resolvIP = null;
try
{
if (!IPAddress.TryParse(serverNameOrURL, out resolvIP))
{
hostEntry = Dns.GetHostEntry(serverNameOrURL);
if (hostEntry != null && hostEntry.AddressList != null && hostEntry.AddressList.Length > 0)
{
if (hostEntry.AddressList.Length == 1)
{
resolvIP = hostEntry.AddressList[0];
isResolved = true;
}
else
{
foreach (IPAddress var in hostEntry.AddressList)
{
if (var.AddressFamily == AddressFamily.InterNetwork)
{
resolvIP = var;
isResolved = true;
break;
}
}
}
}
}
else
{
isResolved = true;
}
}
catch (Exception ex)
{
}
finally
{
resolvedIPAddress = resolvIP;
}
return isResolved;
}
You want to do an nslookup.
Here's an example:
http://www.c-sharpcorner.com/UploadFile/DougBell/NSLookUpDB00112052005013753AM/NSLookUpDB001.aspx
Based on your comment on chaos's answer, you don't want the IP address of a server, you want the IP address of a client. If that's the case, fix your question ... and your answer would be HttpRequest.UserHostAddress.

Categories