Mono and WCF Net.Tcp Binding on all IP Addresses - c#

As mentioned in this article, in .net it's possible to bind a web service to all ip addresses using the "address" 0. However, this doesn't seem to work with mono (version 2.10.8.1).
Here is my example code:
Client:
string ipAddressOfTheService = "192.168.0.23";
EndpointAddress address = new EndpointAddress(string.Format("net.tcp://{0}:8081/myService", ipAddressOfTheService));
NetTcpBinding binding = new NetTcpBinding();
ServiceProxy proxy = new ServiceProxy(binding, address);
if(proxy.CheckConnection())
{
MessageBox.Show("Service is available");
}
else
{
MessageBox.Show("Service is not available");
}
ServiceProxy:
public class ServiceProxy : ClientBase<IMyService>, IMyService
{
public ServiceProxy(Binding binding, EndpointAddress address)
: base(binding, address)
{
}
public bool CheckConnection()
{
bool isConnected = false;
try
{
isConnected = Channel.CheckConnection();
}
catch (Exception)
{
}
return isConnected;
}
}
IMyService:
[ServiceContract]
public interface IMyService
{
[OperationContract]
bool CheckConnection();
}
MyService:
class MyService : IMyService
{
public bool CheckConnection()
{
Console.WriteLine("Check requested!");
return true;
}
}
ServiceHost:
class MyServiceHost
{
static void Main(string[] args)
{
Uri baseAddress = new Uri(string.Format("net.tcp://0:8081/myService");
using (ServiceHost host = new ServiceHost(typeof(MonitoringService), baseAddress))
{
NetTcpBinding binding = new NetTcpBinding();
binding.Security.Mode = SecurityMode.None;
host.AddServiceEndpoint(typeof(IMyService), binding, baseAddress);
host.Open();
Console.WriteLine("The service is ready at {0}", baseAddress);
Console.WriteLine("Press <Enter> to stop the service.");
Console.ReadLine();
host.Close();
}
}
}
If I run this (service and client) on a windows PC using .net all works fine.
On my Linux machine (Raspberry Pi, Debian soft-float) the service start without any problems, however the client cant connect.
If I host the service with its ip address instead of the "0" address everything works correct.
Is this just another bug in mono or do i have to bind to any other ip address instead of the 0?
If it's a bug in mono, are there any workarounds?
(By the way, I'm still searching for an workaround for the port sharing problems with mono/net.tcp, if anyone could help here -> net.tcp port sharing and mono)

Try using + or * instead of 0 to bind to all addresses.
Edit: Or try 0.0.0.0
Edit2: Looks like a bug in Mono. You can report it at https://bugzilla.xamarin.com/index.cgi

I had similar problem in Ubuntu Server 16.04 LTS & Mono JIT compiler version 5.0.1.1 (2017-02/5077205 Thu May 25 09:19:18 UTC 2017).
I got it resolved by adding the following line in /etc/hosts:
0.0.0.0 IP4Any
Then ofcourse, bind the service to IP4Any.

Tutorial to make WCF work through NetTcpBinding on Mono
To use IP address for WCF in Mono u need to write domain name in file /etc/hosts. Then u will be able to use IP address for connecting host and client.
How to write domain:
Open file /etc/hosts on host and add IP.address.of.host HostName

Related

How to fix System.ArgumentNullException when deploying Remote actor on Local Host

I am new to Akka.Net and tried to follow a simple procedure from "Remotely Deploying Actors" tutorial on the getakka.net site.
I however get a System.ArgumentNullException which says 'Value cannot be null. (Parameter 'typeName')'.
Here's my server actor creation block:
var thishocon = HoconLeader.FromFile("akka.net.hocon");
ActorSystem myactorSystem = ActorSystem.Create("server-system", thishocon);
And my akka.net.hocon file for the (console) server:
akka {
actor {
provider = "Akka.Remote.RemoteActorRefProvider, Akka.Remote"
# provider = remote
serializers {
hyperion = "Akka.Serialization.HyperionSerializer,
Akka.Serialization.Hyperion"
}
}
remote {
dot-netty.tcp {
# helios.tcp {
port = 8081 # bound to a specific port
hostname = localhost
}
}
}
The error shows up on the line where I try to reference the remote actor system on the asp.net core client:
Config myhocon = HoconLeader.FromFile("akka.net.hocon");
var actorSystem = ActorSystem.Create("aspnet-actor-system", myhocon);
And here's my akka.net.hocon for the asp.net core client:
akka {
actor {
provider "Akka.Remote.RemoteActorRefProvider, Akka.Remote"
# provider = remote
deployment {
/calculator {
remote = "akka.tcp://server-system#localhost:8081"
}
}
serializers {
hyperion = "Akka.Serialization.HyperionSerializer,
Akka.Serialization.Hyperion"
}
}
remote {
dot-netty.tcp {
# helios.tcp {
port = 0 # bound to a dynamic port assigned by the OS
hostname = localhost
}
}
}
The FromFile method simply creates a config from the specified text document:
public static Config FromFile (string path)
{
var hoconContent = System.IO.File.ReadAllText(path);
return ConfigurationFactory.ParseString(hoconContent);
}
I have set visual studio to start the server before the client of course. The server does start listening on the desired port but then the error happens:
Could this be a firewall issue or what?

C# - Detect public ip adress change, VPN issue

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());
// ...
}

Inbound rule in firewall only works with Admin privileges

I am trying to host a webserver with WPF on the local wifi network and expose a webservice that another device (in my case, an Android) can call while connected to the same wifi network. I have created an inbound rule on the firewall for the port I am using. The webservice call only goes through when the windows app is launched using "Run as Administrator"
Is there a way I can do the same without Admin privileges?
Here is my code -
public class SelfHost
{
WebServiceHost Host;
public void HostServer()
{
var hostIPadd = Util.GetLocalHostIP(); //This returns something like "http://192.168.1.2"
Values.SERVER_PORT_VALUE = "55000";
var uri = new Uri(hostIPadd + ":" + Values.SERVER_PORT_VALUE);
Host = new WebServiceHost(new Service{...}, uri);
//Start host
ServiceEndpoint ep = Host.AddServiceEndpoint(typeof(IService), new WebHttpBinding(), "");
Host.Open();
}
}
public partial class MyWindow : Window
{
public MyWindow()
{
InitializeComponent();
StartHost();
}
private void StartHost()
{
var host = new SelfHost();
var thServer = new System.Threading.Thread(host.HostServer);
thServer.IsBackground = true;
thServer.Start();
}
}
I have created an inbound rule in the firewall with these properties
Protocol type - TCP
Local port - Specific Ports - 55000
Profiles - Public
Action - "Allow the connection"
Programs - "All programs that meet the specified conditions"
I don't quite know why the firewall ignores this exception if the app is not running in Admin. The WebServiceHost object runs fine even if it is not in Admin mode, no errors.
But the webservice call never reaches the server and the request times out.
nothing to do with the firewall, you can't open an http link in a wpf app - for security reasons
see that

Ping class not available in UWP

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;
}

RabbitMQ C# client not talking to Apache Qpid Java Broker

I've installed the M4 release of the Apache Qpid Java broker on a Windows box, and started it using the out-of-the-box configuration (via the qpid-server.bat script).
I'm now trying to publish a message to a queue using the RabbitMQ C# client library (version 1.5.3, compiled for .NET 3.0); my code is:
public void PublishMessage(string message)
{
ConnectionFactory factory = new ConnectionFactory();
factory.Parameters.VirtualHost = "...";
IProtocol protocol = Protocols.FromEnvironment();
using (IConnection conn = factory.CreateConnection(protocol, "localhost", 5672))
{
using (IModel ch = conn.CreateModel())
{
string exchange = "...";
string routingKey = "...";
ch.BasicPublish(exchange, routingKey, null, Encoding.UTF8.GetBytes(message));
}
}
}
Basically, I'm unsure what values to use for factory.Parameters.VirtualHost and the strings exchange and routingKey. I've tried various combinations, but nothing seems to work - the closest I've got is seeing the following in the Qpid server log:
2009-03-19 17:11:04,248 WARN [pool-1-thread-1] queue.IncomingMessage (IncomingMessage.java:198) - MESSAGE DISCARDED: No routes for message - Message[(HC:896033 ID:1 Ref:1)]: 1; ref count: 1
which looks as though the Qpid server is receiving the message, but doesn't know what to do with it.
Any advice on what configuration values I need in my client code (bearing in mind I'm using the default Qpid config in virtualhosts.xml) would be much appreciated. More general information on virtual hosts, exchanges, queues and routing keys, and how Qpid links them all together, would also be very useful.
Thank you in advance,
Alan
Just for reference, I managed to get this working in the end. The code below sends a message to the queue test-queue in the test.direct exchange on the localhost virtual host (all part of the default Qpid broker configuration):
public void PublishMessage(string message)
{
ConnectionFactory factory = new ConnectionFactory();
factory.Parameters.VirtualHost = "/localhost";
IProtocol protocol = Protocols.AMQP_0_8_QPID;
using (IConnection conn = factory.CreateConnection(protocol, "localhost", 5672))
{
using (IModel ch = conn.CreateModel())
{
ch.ExchangeDeclare("test.direct", "direct");
ch.QueueDeclare("test-queue");
ch.QueueBind("test-queue", "test.direct", "TEST", false, null);
ch.BasicPublish("test.direct", "TEST", null, Encoding.UTF8.GetBytes(message));
}
}
}

Categories

Resources