Remoting call never returns. Possibly remoting conflict? - c#

I am trying to establish a .Net remoting call to a thirdparty app. Here's the example code I have been given for that connection (With proprietary names removed):
IDictionary props = new ListDictionary();
props["port"] = 0; // have the Remoting system pick a unique listening port (required for callbacks)
props["name"] = string.Empty; // have the Remoting system pick a unique name
BinaryServerFormatterSinkProvider serverProv = new BinaryServerFormatterSinkProvider();
serverProv.TypeFilterLevel = System.Runtime.Serialization.Formatters.TypeFilterLevel.Full;
_channel = new TcpChannel(props, new BinaryClientFormatterSinkProvider(), serverProv);
ChannelServices.RegisterChannel(_channel, true);
IThirdparty _thirdparty = (IThirdparty)Activator.GetObject(typeof(IThirdparty), "tcp://localhost:9090/Thirdparty.AppIntegration");
//Example API call
_thirdparty.Minimized = !_thirdparty.Minimized;
When this code gets called normally, it hangs at _thirdparty.Minimized and outputs a SocketException in the diagnostics window with the message:
No connection could be made because the target machine actively refused it
The call only returns if I close the Thirdparty app.
I checked netstat -bano and the only app running on port 9090 is the one I am trying to connect to.
So I moved the call to the first few lines of the Main() function in my app and it works just fine. Problem is, that's not where it's supposed to be.
My app contains a lot of other remoting calls to a different server (not on port 9090) as well as a WCF service. My guess is that one of these things are interfering.
Any ideas on how I can figure out why this remoting call never returns?
Update:
I have determined that the SocketException is likely a red herring as these exceptions are created when it works in the 3rd party test app. Also, it looks like the reason why it is hanging is because it is waiting for a Socket.Read() which never gets any data.

It turns out, in .NET remoting, there can only be one TCPClientChannel per AppDomain. Activator.GetObject() uses the first channel that was registered.
The reason why this was blocking is because I already had a TCPClientChannel setup in my AppDomain. This channel had the secure set to false when it was registered. i.e.
ChannelServices.RegisterChannel(_channel, false);
The service I was trying to talk to had security enabled and therefore the remoting call would hang trying to listen to a response that would never come.
The solution is to load my integration into a new AppDomain so that I can configure the TCPChannel differently.

Related

Weird WCF behaviour regarding Timouts and Exceptions

I have created an WCF service hosted inside a normal Windows service. This service is deployed to customers and set up on their servers. Therefore (afaik) I need to establish the WCF proxy dynamically and cannot rely on some prebuilt proxy created by VS or the Silverlight tools. The clients in this case are mobile apps built with Xamarin.Forms.
The Code to create the "Channel":
public void Init(int timeout = 15)
{
ea = new EndpointAddress(string.Format("http://{0}:{1}/{2}", _settingsService.ConnectionIP, _settingsService.ConnectionPort, _settingsService.ConnectionEndpoint));
bhttpb = new BasicHttpBinding(BasicHttpSecurityMode.None);
bhttpb.SendTimeout = TimeSpan.FromSeconds(timeout);
cfIMMC = new ChannelFactory<IMaintMobileContract>(bhttpb, ea);
cfIMMC.Opened += cfIMMC_Opened;
cfIMMC.Faulted += cfIMMC_Faulted;
cfIMMC.Closed += cfIMMC_Closed;
immc = cfIMMC.CreateChannel(ea);
immc.Ping(); // This function is defined by me in the Contract. It only returns true, if the server can be reached.
}
So far everything works fine if the service is running, but the app has to run "offline" and then it gets weird.
When the connection is established there is no EndpointException or anything, and when a function is called it just sits there waiting until the timeout hits.
It would be really nice to get some information whether the WCF service is actually there or not. I have function calls that can take up to multiple minutes and it would be fatal for the app to wait that long when the WCF server is not there at all. How can I achieve that?
Update:
Right now it got even weirder. Now, aprox. 30 seconds after the Ping() fails, I get System.Net.Sockets.SocketException: Connection timed out and System.Net.WebException: Error: ConnectFailure (Connection timed out) out of nowhere.
Update 2 :
Here a pic of the CallStack:
If you need fast feedback regarding whether service is alive or not, then setup additional endpoint (with separate contract containing only Ping method) and set small timeouts for it.
And important part is to set send/receive timeouts to small value as well - this will ensure that Ping method returns/throws fast if service is not available.
As far as I remember WCF does not open channel (== does not connect to server) until you call one of the methods - that's why you don't have exceptions before Ping is called.
About exception after 30 seconds. Where do you see it? I mean is it Visual Studio that breaks there or do you have your application failing with unhandled exception? I'm asking it because I see this in the Xamarin/Mono code:
initConn = new WaitCallback (state => {
try {
InitConnection (state);
} catch {}
});
And it means that even though this exception is thrown after 30 seconds - it'll be swallowed. What really happens is that when request is sent (i.e. when you call Ping()) the runtime tries to open connection in background (your call stack confirms that) and 30 seconds is default Windows timeout for connection. WCF will fail earlier if it has lower timeout set (like in your case), but connection attempt will last for 30 seconds and will complete with exception.
So, my opinion is that you should not care about this exception, unless it somehow stops your application.

'No connection could be made because the target machine actively refused it'

I am working on a 'Smart Device Project' using .Net Framework 3.5. I am trying to connect to some Java SOAP services on a remote server.
In order to do that, I added 'Web References' to my project.
When I try to call my web service I get a WebException 'Unable to connect to the remote server' with the inner exception being 'No connection could be made because the target machine actively refused it'.
I searched quite a lot on the Web and StackOverflow and found a lot of ASP configuration and 'Unavaliable port' answers, but as I have another application using the exact same Service successfully, I can't get why the new one isn't getting through (It did sometimes through my tests so I suppose my client implementation isn't that bad)
I tried to look if there was some connection issue on the port by using some TcpClient:
System.Net.Sockets.TcpClient client = new System.Net.Sockets.TcpClient();
try
{
client.Connect("myServerName", 8087);
MessageBox.Show("Success");
} catch (Exception ex)
{
MessageBox.Show("Failure");
}
finally
{
client.Close();
}
This connection succeed.
Here is a sample on how I call my WebService:
WSServiceExtended srv = new WSServiceExtended();
srv.Proxy = new System.Net.WebProxy();
ServeurWSI wsi = new ServeurWSI();
srv.Url = "http://myServerName:8087/myServerApp/services/myService";
wsr = srv.login(wsi);
The service is called 'Extended' because I overrided the auto-generated one in order to add Cookie managment since I am using the Compact Framework. Following the sample in this thread:
https://social.msdn.microsoft.com/Forums/en-US/34d88228-0b68-4fda-a8cd-58efe6b47958/no-cookies-sessionstate-in-compact-framework?forum=vssmartdevicesvbcs
EDIT:
I made some new tests with the Web references and got it to work.
When I add the Web Reference, I have to put some Url to the Web Service. When I set it with the actual hostname instead of the 'localhost' everything is fine.
But then, since I set it manually to the real address just before the call, it shouldn't matter
srv.Url = "http://myServerName:8087/myServerApp/services/myService";
EDIT2:
I might have forgotten some specifics about my environnement.
The Web Services are exposed on my computer on some Tomcat Server.
The application I am working on is also developped on this computer (That's why I can add Web References by putting 'localhost' in the address)
The application is then deployed on a distant device (Windows CE) that will make calls the Web Services through WIFI (There, localhost wouldn't work then)
I tried calling the Web services from other computers successfully.
I'm beginning to think that there might be some differential between the called Url and the one that is set, otherwise, how would I have a difference in behaviour such as the one described in the first edit?
EDIT3:
Well..Seems like it's not a network issue but a .Net compact framework (usage?) issue...
The Url property of the Web Service implementation is simply ignored and the one in the Reference.cs is used in place.
If someone had some idea on how I could troubleshot this, I would really appreciate it.
That error means that you reached a server and the server said "no way". So you're either hitting the wrong server or the wrong port.
I find the telnet client is useful for testing stuff like this. From the command line, you can do:
telnet [servername] [port]
So something like:
telnet myServerName 8087
If it goes to a blank screen, then it connected successfully. If it does not connect, it'll tell you.
The telnet client is no longer installed by default in Windows 7+, so you'll have to install it. See here for instructions: https://technet.microsoft.com/en-ca/library/cc771275
If the connection does open, you could paste in an actual HTTP request to see what happens. A simple GET would look something like this:
GET /myServerApp/services/myService HTTP/1.1
Host: myServerName:8087
One reason for this error can be that the service binds to only a certain IP address. It could well be that the service only listens on the IP that is assigned to the host name, but not on the localhost IP (127.0.0.1).
For example:
If the host myServerName has the public IP 192.168.0.1, your service can choose to listen on all IPs assigned to the host (sometimes specifying 0.0.0.0), or it can specifically listen on 192.168.0.1 only. In that case you will not be able to connect through 127.0.0.1, because the service simply doesn't listen on that IP.
You can "use" this inverse of this feature to make a service accessible only to local clients, not on the public IP-Address, by listening on 127.0.0.1 only, but not on the public IP. This is sometimes used on Linux for example to make MySQL only accessible on the host itself.
I was starting to forget this post but I finally found the problem that was messing things up and it has nothing to do with programmation.
I was doing the calls while the device was connected to the computer via the 'Windows Mobile Device Center' allowing to access the device from Windows.
While connected, the host provided is ignored and all calls on the specified port are handled by the connected computer.
Disconnecting the device allows to communicate properly...

HPC BrokerClient takes a long time to execute and throws an error on trying to get results

I am trying to get my sample WCF service to run on a on-premise HPC 2012 SP1 cluster. It's an 2012 HPC WCF application. My test service is deployed to all Compute nodes in a
cluster and configuration file is deployed on a head node too. In my client application I am using BrokerClient wrapper over my service proxy client. By using HPC Cluster
Manager I can see that my service is invoked and ran, but it is very slow, it takes him about 5 minutes to finish executing (and it's a simple test service, without intensive
operations). And also in my client application I am getting he following error after tasks finished executing on a cluster:
"Broker is unavailable due to loss of heartbeat.
Make sure you can connect to the broker node, the HpcBroker service is running on the broker node and the session is still running."
here is my client code:
SessionStartInfo info = new SessionStartInfo(this.textBox1.Text, this.textBox2.Text);
info.SessionResourceUnitType = SessionUnitType.Core;
info.Secure = false;
info.MinimumUnits = 1;
info.MaximumUnits = 1;
using (Session s = Session.CreateSession(info))
{
NetTcpBinding binding = new NetTcpBinding(SecurityMode.None, false);
using (BrokerClient<IHpcTestService> client = new BrokerClient<IHpcTestService>(s, binding))
{
ApplyCalculationsRequest request = new ApplyCalculationsRequest("test");
client.SendRequest<ApplyCalculationsRequest>(request);
client.EndRequests();
foreach (var resp in client.GetResponses<ApplyCalculationsResponse>())
{
this.label3.Text = resp.Result.ApplyCalculationsResult;
break;
}
}
}
P.S. when I try to use plain proxy client, without BrokerClient wrapper, everything works just fine.
Any ideas on the above?
Regrading the slowness, you'd need to provide more specifics about what kind of slow down you are talking about. You can see slowness in various areas and each one is caused by something different.
If it is slowness in Job Creation, this happens on the Head Node
If it is slowness in submission of tasks to job and executing EndRequests, this happens on the Broker node as the requests are written to the MSMQ folder on the broker node brokering the job.
If it is slowness in job runtime, then this is an issue with the worker nodes; this could be caused by a slow database connection, or general slowness in your application, or if you are using central shared location for the service instead of a local copy this could also cause slowness.
As for the error you are getting:
"Broker is unavailable due to loss of heartbeat. Make sure you can connect to the broker node, the HpcBroker service is running on the broker node and the session is still running."
When using the BrokerClient wrapper for whatever reason HPC sends 2 final callback messages instead of just the one. For any given job the final task in the list (but not necessarily the last executed task in the list) has a bool that designates it as the last task. When you have received all callbacks and you re-attach to the job and close it, it sends out a final message which you cannot open because the service channel was closed. I do not know why it does this when you have a BrokerClient wrapper in place; I've yet to figure that out. Essentially if I don't see that message more than once per job I ignore it at this point.
Out of curiosity can you post your code related to using a Proxy Client?

Why am I getting an exception (TCP error code 10061) when attempting to communicate between 2 applications using WCF?

I am trying to use WCF to setup IPC between 2 running windows applications.
I want to start out by saying that I know there are other (better?) ways to implement
this solution. But, due to some pre-existing design considerations/constraints, I'm bound to using:
- netTcpBinding
- DuplexChannelFactory<> to support bidirectional communication
All the applications, services, etc reside on the same machine as we will be
installing everything on a single dedicated piece hardware running MS Windows.
So the schematic kind of looks like this
WPFApp1
(Contains ReportingFacilityInterface definition)
Returns notifications as separate callbacks to WPFApp2
^
|
|
V
ReportingFacilityInterfaceProxy
^
|
|
V
WPFApp2 (needs to call exposed methods on WPF1 ReportingFacilityInterface object)
I've created my WCF "service" class and contracts.
I'm using a proxy dll to facilitate the communication.
Here's the sequence of events:
1)WPFApp1 starts up and instantiates an instance of the exposed service class
ReportingFacilityInterface = new ReportingFacility.ReportingFacilityInterface();
This starts up fine.
2) WPFApp2 startsup and initializes instance of proxy object
reportingFacilityProxy = new ReportingFacilityInterfaceProxy.ReportingFacilityProxy();
This instantiates the proxy object, which results in this getting called:
reportingFacilityInterface = DuplexChannelFactory<IReportingFacilityInterface>.CreateChannel(objContext, "RPIEndPointConfiguration");
This seems to run and return successfuly.
3) WPFApp2 calls a on the object (through the proxy)
reportingFacilityInterface.Initialize(configuration);
I get an exception with the following detail:
Could not connect to net.tcp://localhost:8732/ReportingFacility.
The connection attempt lasted for a time span of 00:00:02.1931255.
TCP error code 10061: No connection could be made because the target machine actively refused it 127.0.0.1:8732
I examined my current port usage using the CurrPorts application and noticed that port #8732 does is not in the list of currently active/used ports on my machine.
Since I'm pretty green # the world of WCF, I'm kind of stumped here.
As I mentioned above, all these are running on the same (dedicated) piece of Windows 7 hardware, so permissions/roles should not be an issue.
I think I'm pretty close here, but am just missing something.
Thanks,
JohnB
I'd:
Verify your server config to be sure about service endpoint address
Run the Service Trace Viewer Tool (SvcTraceViewer.exe)
Add some basicHttpBinding endpoint to be sure you can access it from your browser
I resolved the same issue by going to services and start Net.tcp listener adapter.
Also, you can find more solutions here
http://blogs.ajithbhat.com/2010/06/tcp-error-code-10061-no-connection.html

How to determine if remoting channel is already registered

In my ASP.NET application, I have a line in the global application start event that configures the client remoting channel by calling RemotingConfiguration.Configure().
This works well the first time, but when my web application gets recycled, the application start event is fired again causing the following remoting exception:
Remoting configuration failed with the exception 'System.Runtime.Remoting.RemotingException: The channel 'tcp' is already registered.
I would like to detect if the channel is already configured so that I can avoid getting this exception.
Try ChannelServices.RegisteredChannels
http://msdn.microsoft.com/en-us/library/system.runtime.remoting.channels.channelservices.registeredchannels(VS.71).aspx
I've been having this problem too.
The trouble is that you can stop the application that called RemotingConfiguration.Configure() but that doesn't make the channel available. Its something to do with ports or it might just be the name of the channel, I'm not sure.
The solution I found which seems to work is to get the registered channels and unregister the channel you want to remove.
Here is some code
RemotingConfiguration.Configure(appConfig, false);
// do this to unregister the channel
IChannel[] regChannels = ChannelServices.RegisteredChannels;
IChannel channel = (IChannel)ChannelServices.GetChannel(regChannels[0].ChannelName);
ChannelServices.UnregisterChannel(channel);
RemotingConfiguration.Configure(appConfig, false); // this is just a test to see if we get an error
I hope this works for you, it has for me
But what would you do if you found it was already registered?
In any case, I just wanted to make sure you knew that .NET Remoting has been deprecated in favor of WCF.

Categories