I think this is a simple problem. I have an IP address and I want to ping it and get its duration. However, in UWP there is no Ping class.
How do I ping an IP without this class? Should I connect to a specific port instead?
Add the System.Net.Ping NuGet package to your project
try to ping Port 80. Normally thats the port you have to use if you are pinging a website.
try this:
HostName host = new HostName("www.google.com");
var eps = await DatagramSocket.GetEndpointPairsAsync(host , "80");
if(eps.Count >= 1)
{
return true;
}
else
{
return false;
}
Related
With following code I am able to track public IP changes of my desktop application. This should be able to track if either the public IP changed or the user enabled a VPN to change his public IP. This code is run on application launch and used once again when a check is needed:
public class PublicIP
{
IPAddress last_ip=null;
DateTime timestamp_lastipchange;
public void UpdateIP()
{
List<string> hosts = new List<string>()
{
"https://api.ipify.org",
"https://ipinfo.io/ip",
"https://checkip.amazonaws.com",
"https://wtfismyip.com/text",
"http://icanhazip.com"
};
using(WebClient webclient = new WebClient())
{
foreach(string host in hosts)
{
//Download each string from hosts until an IP could be fetched
try{
var newip = IPAddress.Parse(webclient.DownloadString(service)); //Downloading the string
if(!newip.IsEqual(last_ip) && last_ip!=null) timestamp_lastipchange = DateTime.Now; //Check if the ip changed, if the last known ip does not exists skipp this step
last_ip = newip; //Save last known ip
return;
}
catch { }
}
}
}
}
This approach seems to work pretty well, however during UnitTesting some workflows do not fetch a new IP:
IP change by switching networks: change gets successfully detected
IP changed by provider: change gets successfully detected
VPN was enabled when the application was launched and is then turned off:
change gets successfully detected
VPN was disabled on application start and is turned on during runtime:
change does not get detected. Webclient.DownloadString() still returns the same IP as if the VPN was not enabled.
I am not really sure what is happening in workflow nr 4. Do I have to manually select the new network interface (VPN)? Or is this a caching problem on the client/server side?
WebClient is high-level and might using static pool behind-the-scene (and also deprecated). You might try using HttpClient instead, because HttpClient handle connection via its message handler, and the default one is not static, which means this should work:
using(var httpClient = new HttpClient())
{
var newip = IPAddress.Parse(webclient.GetStringAsync(service)
.ConfigureAwait(false).GetAwaiter().GetResult());
// ...
}
I want to create a gRPC server and bind it to a random port.
The documentation states that port 0 (ServerPort.PickUnused = 0) can be passed to achieve this:
var server = new Server
{
Ports = { new ServerPort("0.0.0.0", ServerPort.PickUnused, ServerCredentials.Insecure) }
};
// ... adding some services
server.Start();
How can I determine which port has been assigned to the server?
The passed ServerPort still mentions 0:
var enumerator = server.Ports.GetEnumerator();
enumerator.MoveNext();
var serverPort = enumerator.Current as ServerPort;
Debug.Log($"RPC Server started on port {serverPort.Port}");
// Out: RPC Server started on port 0
Sometimes reading the WHOLE documentation page BEFORE googling around would save so much time.
ServerPort has a property named BoundPort (quote: "The port actually bound by the server.
This is useful if you let server pick port automatically.")
This returns the actual port:
Debug.Log($"RPC Server started on port {serverPort.BoundPort}");
I am writing a web server as a Universal Windows Platform app in C#. Here is my code so far:
sealed partial class App : Application
{
int port = 8000;
/// <summary>
/// Initializes the singleton application object. This is the first line of authored code
/// executed, and as such is the logical equivalent of main() or WinMain().
/// </summary>
public App()
{
StartServer();
}
private void StartServer()
{
StreamSocketListener listener = new StreamSocketListener();
listener.BindServiceNameAsync(port.ToString());
Debug.WriteLine("Bound to port: " + port.ToString());
listener.ConnectionReceived += async (s, e) =>
{
Debug.WriteLine("Got connection");
using (IInputStream input = e.Socket.InputStream)
{
var buffer = new Windows.Storage.Streams.Buffer(2);
await input.ReadAsync(buffer, buffer.Capacity, InputStreamOptions.Partial);
}
using (IOutputStream output = e.Socket.OutputStream)
{
using (Stream response = output.AsStreamForWrite())
{
response.Write(Encoding.ASCII.GetBytes("Hello, World!"), 0, 1);
}
}
};
}
}
I tried connecting to the server using this address:
http://127.0.0.1:8000/C:/pathtohtmlfile/htmlfile.html
However, the connection times out. I am not sure if it is a problem with the C# code or with something else.
Raymond Zuo's solution really works. But the main thing not to forget are capabilities in Packages.appxmanifest. In order to run the server in Private networks one should add:
<Capability Name="privateNetworkClientServer" />
And in order to run the server in Public network:
<Capability Name="internetClientServer" />
If you want to host a server in uwp app, be sure these things:
your device which run this code (Device A) and device which your web browser run (Device B) must at a same LAN. And you cannot use the browser in Device A to access your service.
use WIFI to access your service.
your app must be at the state of running.
you should write a method to get ip address, but not 127.0.0.1:
public static string FindIPAddress()
{
List<string> ipAddresses = new List<string>();
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))
{
string ipAddress = hn.DisplayName;
ipAddresses.Add(ipAddress);
}
}
if (ipAddresses.Count < 1)
{
return null;
}
else if (ipAddresses.Count == 1)
{
return ipAddresses[0];
}
else
{
return ipAddresses[ipAddresses.Count - 1];
}
}
It is possible to host a web service on phone/tablet.
It is possible to host a web service in a Window Universal App. I followed the example from http://www.dzhang.com/blog/2012/09/18/a-simple-in-process-http-server-for-windows-8-metro-apps , also followed the three first steps from Raymond Zuo's solution and finally I also put the firewall down. Unfortunately, I was not able to run on localhost even though I followed the answers from here Cannot connect to localhost in windows store application . I am currently doing java http requests to the Universal Platform App. Definitely, server and client seem to be required to run on different hosts.
I am searching something replacement of System.Net.Sockets.AddressFamily.InterNetwork. I found HostName but unable to find something that can do like AdressFamily does. Actually, I am converting following code in winRT. I know winRT supports Windows.Networking.Sockets etc. Please describe some solution.
The code is,
if (System.Net.Sockets.AddressFamily.InterNetwork == _address.AddressFamily && _address.AddressFamily == address.AddressFamily)
{
long longLocal = BitConverter.ToInt32(_address.GetAddressBytes(), 0);
long longNetMask = BitConverter.ToInt32(_netmask.GetAddressBytes(), 0);
long longRemote = BitConverter.ToInt32(address.GetAddressBytes(), 0);
}
_address is also IPAdress
Well AddressFamily does not directly supports WinRT/Metro project so what you need to do is check the ipAddress information like this
using Windows.Networking;
using Windows.Networking.Sockets;
HostName serverHost = new HostName("www.contoso.com");
StreamSocket clientSocket = new Windows.Networking.Sockets.StreamSocket();
// Try to connect to the remote host
await clientSocket.ConnectAsync(serverHost, "http");
var ipAddress = clientSocket.Information.RemoteAddress.DisplayName
To check your condition use _address.Type == HostNameType.Ipv4 then do something but make sure that GetAddressBytes do not exist in HostName class so for that you need to write your own function to convert an ipAddress into bytes.
I need to get the actual local network IP address of the computer (e.g. 192.168.0.220) from my program using C# and .NET 3.5. I can't just use 127.0.0.1 in this case.
How can I accomplish this?
If you are looking for the sort of information that the command line utility, ipconfig, can provide, you should probably be using the System.Net.NetworkInformation namespace.
This sample code will enumerate all of the network interfaces and dump the addresses known for each adapter.
using System;
using System.Net;
using System.Net.NetworkInformation;
class Program
{
static void Main(string[] args)
{
foreach ( NetworkInterface netif in NetworkInterface.GetAllNetworkInterfaces() )
{
Console.WriteLine("Network Interface: {0}", netif.Name);
IPInterfaceProperties properties = netif.GetIPProperties();
foreach ( IPAddress dns in properties.DnsAddresses )
Console.WriteLine("\tDNS: {0}", dns);
foreach ( IPAddressInformation anycast in properties.AnycastAddresses )
Console.WriteLine("\tAnyCast: {0}", anycast.Address);
foreach ( IPAddressInformation multicast in properties.MulticastAddresses )
Console.WriteLine("\tMultiCast: {0}", multicast.Address);
foreach ( IPAddressInformation unicast in properties.UnicastAddresses )
Console.WriteLine("\tUniCast: {0}", unicast.Address);
}
}
}
You are probably most interested in the UnicastAddresses.
Using Dns requires that your computer be registered with the local DNS server, which is not necessarily true if you're on a intranet, and even less likely if you're at home with an ISP. It also requires a network roundtrip -- all to find out info about your own computer.
The proper way:
NetworkInterface[] nics = NetworkInterface.GetAllNetworkInterfaces();
foreach(NetworkInterface adapter in nics)
{
foreach(var x in adapter.GetIPProperties().UnicastAddresses)
{
if (x.Address.AddressFamily == AddressFamily.InterNetwork && x.IsDnsEligible)
{
Console.WriteLine(" IPAddress ........ : {0:x}", x.Address.ToString());
}
}
}
(UPDATE 31-Jul-2015: Fixed some problems with the code)
Or for those who like just a line of Linq:
NetworkInterface.GetAllNetworkInterfaces()
.SelectMany(adapter=> adapter.GetIPProperties().UnicastAddresses)
.Where(adr=>adr.Address.AddressFamily == AddressFamily.InterNetwork && adr.IsDnsEligible)
.Select (adr => adr.Address.ToString());
In How to get IP addresses in .NET with a host name by John Spano, it says to add the System.Net namespace, and use the following code:
//To get the local IP address
string sHostName = Dns.GetHostName ();
IPHostEntry ipE = Dns.GetHostByName (sHostName);
IPAddress [] IpA = ipE.AddressList;
for (int i = 0; i < IpA.Length; i++)
{
Console.WriteLine ("IP Address {0}: {1} ", i, IpA[i].ToString ());
}
As a machine can have multiple ip addresses, the correct way to figure out your ip address that you're going to be using to route to the general internet is to open a socket to a host on the internet, then inspect the socket connection to see what the local address that is being used in that connection is.
By inspecting the socket connection, you will be able to take into account weird routing tables, multiple ip addresses and whacky hostnames. The trick with the hostname above can work, but I wouldn't consider it entirely reliable.
If you know there are one or more IPv4 addresses for your computer, this will provide one of them:
Dns.GetHostAddresses(Dns.GetHostName())
.First(a => a.AddressFamily == AddressFamily.InterNetwork).ToString()
GetHostAddresses normally blocks the calling thread while it queries the DNS server, and throws a SocketException if the query fails. I don't know whether it skips the network call when looking up your own host name.