Parsing host:port expressions - c#

What's the best and simplest way to parse an environment variable of the following possible forms: host[:port]
redis
redis:6379
10.0.0.72
10.0.0.72:6379
my.domain.name
my.domain.name:6379
The inputs are never prepended with a protocol.
The end goal is to parse out the host and port in order to create an object of type System.Net.IPEndPoint, possibly after using Dns.GetHostAddresses(host)[0] depending on whether there is an ip or a hostname supplied in the environment variable.
The purpose is helping dotnet core apps inside various docker containers discover each other according to values specified in their environment variables.
I'm hoping to make use of parsing utilities already available in the dotnet core libraries rather than roll my own parser.
new Uri("redis:6379") produces invalid results.
new Uri("https://redis:6379") produces a Uri object with correct host and port properties, but it seems ridiculous to me that it should be necessary to malform all the inputs by prepending "https://" just to get the Uri object to parse it correctly.
new Uri("https://redis") incorrectly sets the Port property as 443 and doesn't indicate that it wasn't supplied in the user input.
If it's possible to skip parsing steps and resolve straight to IPEndPoint with no in-between steps, that would be my preferred answer.
This is what I'm using at the moment, with error handling removed. Have you got something better?
IPEndPoint ParseGateway(string input) {
var parts = input.Split(':');
var host = parts[0];
var port = parts.Length > 1 ? int.Parse(parts[1]) : DEFAULT_GATEWAY_PORT;
var ip = Dns.GetHostAddresses(host)[0];
return new IPEndPoint(ip, port);
}

Use string method SubString as shown below :
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
namespace ConsoleApplication1
{
class Program
{
static void Main(string[] args)
{
string[] inputs = {
"redis",
"redis:6379",
"10.0.0.72",
"10.0.0.72:6379",
"my.domain.name",
"my.domain.name:6379"
};
string address = "";
string port = "";
foreach (string input in inputs)
{
if (input.Contains(":"))
{
address = input.Substring(0, input.IndexOf(":"));
port = input.Substring(input.IndexOf(":") + 1);
}
else
{
address = input;
port = "";
}
Console.WriteLine("Address : '{0}'; Port : '{1}'", address, port);
}
Console.ReadLine();
}
}
}

Related

Named Pipes IPC: Python server, C# Client

Title sums it up. There are plenty of examples around with a c# server and python client communicating back and forth.
I'd like to understand how I can instead create a python server and c# client for some interprocess communication.
I managed to find a solution. To begin, I'd first like to clarify some confusing terminology and obscure naming conventions used in dotnet core.
It appears that the NamedPipeServerStream and NamedPipeClientStream don't actually operate on named pipes but instead on unix domain sockets. This means that we must use sockets to communicate between processes rather than FIFO files.
Another frustration I find with dotnet core is that when creating a socket or connecting to one, the NamedPipeServerStream and NamedPipeClientStream classes will add "CoreFxPipe_" to the beginning of the socket name. See related question.
Python Server
#!/usr/bin/python3
import socket
import os
import struct
SOCK_PATH = "/tmp/CoreFxPipe_mySocket"
with socket.socket(socket.AF_UNIX, socket.SOCK_STREAM) as sock:
try:
os.remove(SOCK_PATH)
except OSError:
pass
sock.bind(SOCK_PATH)
sock.listen()
conn, addr = sock.accept()
with conn:
try:
while True:
amount_expected = struct.unpack('I', conn.recv(4))[0]
print("amount_expected :", amount_expected)
message = conn.recv(amount_expected)
print("Received message : ", message.decode())
# Send data
message_rev = message[::-1].decode()
print("Sent message (reversed) : ", message_rev)
conn.sendall(
struct.pack(
'I',
len(message_rev)
)
+ message_rev.encode('utf-8')
)
except (struct.error, KeyboardInterrupt) as e:
print(e)
finally:
print('closing socket')
C# Client
using System;
using System.IO;
using System.IO.Pipes;
using System.Text;
class PipeClient
{
static void Main(string[] args)
{
using (NamedPipeClientStream pipeClient =
new NamedPipeClientStream(".", "mySocket", PipeDirection.InOut))
{
// Connect to the pipe or wait until the pipe is available.
Console.WriteLine("Attempting to connect to pipe...");
pipeClient.Connect();
try
{
// Read user input and send that to the client process.
using (BinaryWriter _bw = new BinaryWriter(pipeClient))
using (BinaryReader _br = new BinaryReader(pipeClient))
{
while (true)
{
//sw.AutoFlush = true;
Console.Write("Enter text: ");
var str = Console.ReadLine();
var buf = Encoding.ASCII.GetBytes(str); // Get ASCII byte array
_bw.Write((uint)buf.Length); // Write string length
_bw.Write(buf); // Write string
Console.WriteLine("Wrote: \"{0}\"", str);
Console.WriteLine("Let's hear from the server now..");
var len = _br.ReadUInt32();
var temp = new string(_br.ReadChars((int)len));
Console.WriteLine("Received from client: {0}", temp);
}
}
}
// Catch the IOException that is raised if the pipe is broken
// or disconnected.
catch (IOException e)
{
Console.WriteLine("ERROR: {0}", e.Message);
}
}
Console.Write("Press Enter to continue...");
}
}
Sources:
https://abgoswam.wordpress.com/2017/07/13/named-pipes-c-python-net-core/
https://realpython.com/python-sockets/
https://unix.stackexchange.com/questions/75904/are-fifo-pipe-unix-domain-socket-the-same-thing-in-linux-kernel

Get DHCP IP address of Raspbery Pi

I have a .NetCore c# app.
I am using it in a Raspberry Pi device running Raspbian.
I am trying to get my assigned DHCP IP address.
I have tried many things.
They all return 127.0.0.1.
This is using web sockets. The server is written in c# and client is written in JS.
Any ideas apart from the usual examples out there?
Latest attempts:
public void GetIPAddress()
{
List<string> IpAddress = new List<string>();
var Hosts = System.Windows.Networking.Connectivity.NetworkInformation.GetHostNames().ToList();
foreach (var Host in Hosts)
{
string IP = Host.DisplayName;
IpAddress.Add(IP);
}
IPAddress address = IPAddress.Parse(IpAddress.Last());
Console.WriteLine(address);
}
Tells me that "The type or namespace name 'Networking' does not exist in the namespace 'System.Windows' (are you missing an assembly reference?)"
public static string GetLocalIPAddress()
{
var localIP = "";
try
{
var host = Dns.GetHostEntry(Dns.GetHostName());
foreach (var ip in host.AddressList)
{
if (ip.AddressFamily == AddressFamily.InterNetwork)
{
localIP = ip.ToString();
Console.WriteLine(localIP);
//break;
}
}
}
catch ( Exception e )
{
Console.WriteLine( e );
Environment.Exit( 0 );
}
return localIP;
}
Returns 127.0.0.1
should also point out that using 127.0.0.1 as the web socket connection does not work for some reason
Rather than rely on .Net Core libraries/framework I instead googled linux commands to get the ip address as I know it does this.
If I open a Terminal window on the Pi and type in:
hostname -I
it will return the ip address.
So, my next step was to run this linux command from within C#.
For this I can use the process class and redirct the output:
//instantiate a new process with c# app
var proc = new Process
{
StartInfo = new ProcessStartInfo
{
FileName = "hostname", //my linux command i want to execute
Arguments = "-I", //the argument to return ip address
UseShellExecute = false,
RedirectStandardOutput = true, //redirect output to my code here
CreateNoWindow = true /do not show a window
}
};
proc.Start(); //start the process
while (!proc.StandardOutput.EndOfStream) //wait until entire stream from output read in
{
Console.WriteLine( proc.StandardOutput.ReadLine()); //this contains the ip output
}

2 Different IP Address

I have 2 methods in my program to retrieve the IP Address of the Computer.
1st
public string GetIP1()
{
//using System.Net.Sockets;
return Dns.GetHostEntry(Dns.GetHostName()).AddressList.FirstOrDefault(ip => ip.AddressFamily == AddressFamily.InterNetwork).ToString();
}
2nd
public string GetIP2()
{
//using System.IO;
String direction = "";
try
{
WebRequest request = WebRequest.Create("http://checkip.dyndns.org/");
using (WebResponse response = request.GetResponse())
using (StreamReader stream = new StreamReader(response.GetResponseStream()))
{
direction = stream.ReadToEnd();
}
//Search for the ip in the html
int first = direction.IndexOf("Address: ") + 9;
int last = direction.LastIndexOf("</body>");
direction = direction.Substring(first, last - first);
}
catch(Exception){ }
return direction;
}
The 1st code returns an IP that looks like 10.xx.xx.x, and the 2nd code returns IP Address such as 121.xx.xx.xx
Why does the output of these two methods differ?
Obviously, you are behind some NAT.
So by running first code you're receiving your internal network address, and second code gives you real (external) IP address from which your network has access to Internet.
That's because second method is just call to external website determining your IP, and that website only can determine real IP address, not internal one.
In the first method, you are getting the IP Address of your internal network, so if you are behind a router, you will get an internal IP address. This is the address you would see if you ran ipconfig /all from a command prompt.
In the second method you are getting your internet (external) IP address.

How to get internet IP address from C# Windows App [duplicate]

This question already has answers here:
Closed 12 years ago.
Possible Duplicates:
how to get my own IP address in C#?
how to get ip address of machine in c#
Hi all, I am currently developing a c# application for windows using WPF. I would like to get the computers external IP address i.e. the internet address not the local computer ip address or the local router address.
Thanks for your help.
Like stated earlier, you need an external web server. An easy call to HTTP GET with the URL "http://checkip.dyndns.org/" will get you a simple text string with your IP.
You need to have a web server sitting somewhere in the cloud so that you can call and that will be able to give you your external IP address.
Looks like this one is free.
[EDIT]
A simple request to here will get you your ip.
This is a way to get any network address (not necessarily the internet ip) as pointed out in the comments:
IPAddress host = IPAddress.None;
foreach (IPAddress ip in Dns.GetHostAddresses(Dns.GetHostName()))
{
host = ip;
if (ip.AddressFamily == AddressFamily.InterNetwork)
break;
}
The only way I have found is to do a httpWebRequest to http://www.whatismyip.com/automation/n09230945.asp and parse the results for the ip
You can try connecting to whatismyip.com, as shown in the code below:
using System;
using System.Net;
using System.Text;
using System.Text.RegularExpressions;
namespace DreamInCode.Snippets
{
public class IpFinder
{
public static IPAddress GetExternalIp()
{
string whatIsMyIp = "http://whatismyip.com";
string getIpRegex = #"(?<=<TITLE>.*)\d*\.\d*\.\d*\.\d*(?=</TITLE>)";
WebClient wc = new WebClient();
UTF8Encoding utf8 = new UTF8Encoding();
string requestHtml = "";
try
{
requestHtml = utf8.GetString(wc.DownloadData(whatIsMyIp));
}
catch (WebException we)
{
// do something with exception
Console.Write(we.ToString());
}
Regex r = new Regex(getIpRegex);
Match m = r.Match(requestHtml);
IPAddress externalIp = null;
if (m.Success)
{
externalIp = IPAddress.Parse(m.Value);
}
return externalIp;
}
}
}
NOTE: The code comes from this post http://www.dreamincode.net/forums/topic/24692-showing-the-external-ip-address-in-c%23/ .

Any way to turn the "internet off" in windows using c#?

I am looking for pointers towards APIs in c# that will allow me to control my Internet connection by turning the connection on and off.
I want to write a little console app that will allow me to turn my access on and off , allowing for productivity to skyrocket :) (as well as learning something in the process)
Thanks !!
If you're using Windows Vista you can use the built-in firewall to block any internet access.
The following code creates a firewall rule that blocks any outgoing connections on all of your network adapters:
using NetFwTypeLib; // Located in FirewallAPI.dll
...
INetFwRule firewallRule = (INetFwRule)Activator.CreateInstance(
Type.GetTypeFromProgID("HNetCfg.FWRule"));
firewallRule.Action = NET_FW_ACTION_.NET_FW_ACTION_BLOCK;
firewallRule.Description = "Used to block all internet access.";
firewallRule.Direction = NET_FW_RULE_DIRECTION_.NET_FW_RULE_DIR_OUT;
firewallRule.Enabled = true;
firewallRule.InterfaceTypes = "All";
firewallRule.Name = "Block Internet";
INetFwPolicy2 firewallPolicy = (INetFwPolicy2)Activator.CreateInstance(
Type.GetTypeFromProgID("HNetCfg.FwPolicy2"));
firewallPolicy.Rules.Add(firewallRule);
Then remove the rule when you want to allow internet access again:
INetFwPolicy2 firewallPolicy = (INetFwPolicy2)Activator.CreateInstance(
Type.GetTypeFromProgID("HNetCfg.FwPolicy2"));
firewallPolicy.Rules.Remove("Block Internet");
This is a slight modification of some other code that I’ve used, so I can’t make any guarantees that it’ll work. Once again, keep in mind that you'll need Windows Vista (or later) and administrative privileges for this to work.
Link to the firewall API documentation.
This is what I am currently using (my idea, not an api):
System.Diagnostics;
void InternetConnection(string str)
{
ProcessStartInfo internet = new ProcessStartInfo()
{
FileName = "cmd.exe",
Arguments = "/C ipconfig /" + str,
WindowStyle = ProcessWindowStyle.Hidden
};
Process.Start(internet);
}
Disconnect from internet: InternetConnection("release");
Connect to internet: InternetConnection("renew");
Disconnecting will just remove the access to internet (it will show a caution icon in the wifi icon).
Connecting might take five seconds or more.
Out of topic:
In any cases you might want to check if you're connected or not (when you use the code above), I better suggest this:
System.Net.NetworkInformation;
public static bool CheckInternetConnection()
{
try
{
Ping myPing = new Ping();
String host = "google.com";
byte[] buffer = new byte[32];
int timeout = 1000;
PingOptions pingOptions = new PingOptions();
PingReply reply = myPing.Send(host, timeout, buffer, pingOptions);
return (reply.Status == IPStatus.Success);
}
catch (Exception)
{
return false;
}
}
There are actually a myriad of ways to turn off (Read: break) your internet access, but I think the simplest one would be to turn of the network interface that connects you to the internet.
Here is a link to get you started:
Identifying active network interface
Here's a sample program that does it using WMI management objects.
In the example, I'm targeting my wireless adapter by looking for network adapters that have "Wireless" in their name. You could figure out some substring that identifies the name of the adapter that you are targeting (you can get the names by doing ipconfig /all at a command line). Not passing a substring would cause this to go through all adapters, which is kinda severe. You'll need to add a reference to System.Management to your project.
using System;
using System.Management;
namespace ConsoleAdapterEnabler
{
public static class NetworkAdapterEnabler
{
public static ManagementObjectSearcher GetWMINetworkAdapters(String filterExpression = "")
{
String queryString = "SELECT * FROM Win32_NetworkAdapter";
if (filterExpression.Length > 0)
{
queryString += String.Format(" WHERE Name LIKE '%{0}%' ", filterExpression);
}
WqlObjectQuery query = new WqlObjectQuery(queryString);
ManagementObjectSearcher objectSearcher = new ManagementObjectSearcher(query);
return objectSearcher;
}
public static void EnableWMINetworkAdapters(String filterExpression = "")
{
foreach (ManagementObject adapter in GetWMINetworkAdapters(filterExpression).Get())
{
//only enable if not already enabled
if (((bool)adapter.Properties["NetEnabled"].Value) != true)
{
adapter.InvokeMethod("Enable", null);
}
}
}
public static void DisableWMINetworkAdapters(String filterExpression = "")
{
foreach (ManagementObject adapter in GetWMINetworkAdapters(filterExpression).Get())
{
//If enabled, then disable
if (((bool)adapter.Properties["NetEnabled"].Value)==true)
{
adapter.InvokeMethod("Disable", null);
}
}
}
}
class Program
{
public static int Main(string[] args)
{
NetworkAdapterEnabler.DisableWMINetworkAdapters("Wireless");
Console.WriteLine("Press any key to continue");
var key = Console.ReadKey();
NetworkAdapterEnabler.EnableWMINetworkAdapters("Wireless");
Console.WriteLine("Press any key to continue");
key = Console.ReadKey();
return 0;
}
}
}
public static void BlockingOfData()
{
INetFwPolicy2 firewallPolicy = (INetFwPolicy2)Activator.CreateInstance(Type.GetTypeFromProgID("HNetCfg.FwPolicy2"));
firewallPolicy.set_DefaultOutboundAction(NET_FW_PROFILE_TYPE2_.NET_FW_PROFILE2_DOMAIN, NET_FW_ACTION_.NET_FW_ACTION_BLOCK);
firewallPolicy.set_DefaultOutboundAction(NET_FW_PROFILE_TYPE2_.NET_FW_PROFILE2_PRIVATE, NET_FW_ACTION_.NET_FW_ACTION_BLOCK);
firewallPolicy.set_DefaultOutboundAction(NET_FW_PROFILE_TYPE2_.NET_FW_PROFILE2_PUBLIC, NET_FW_ACTION_.NET_FW_ACTION_BLOCK);
}

Categories