I have a problem about checking a WCF connection is opened. My WCF Connection is bi-directional. I use State property to check the connection's state at client. My function:
private bool ConnectionIsOpen()
{
if (m_Service != null && (m_Service.State | CommunicationState.Opened) == CommunicationState.Opened)
{
return true;
}
return false;
}
I create a service which is a thread running every 10 seconds to check the connection's state. I use the method ConnectionIsOpen() for checking. Everything is well on running on Windows XP. However there is a problem when running on Windows 7.
When I unplug the network cable to create to disconnect, If running application on Windows XP, checking connection's State is Faulted but if running on Windows 7, checking connection' State is still Opened.
Anyone can help me how to check a connection is openned or not in this case. Thanks.
This will always be true:
(m_Service.State | CommunicationState.Opened) == CommunicationState.Opened
Example, m_Service.State = 0:
0 | CommuncationState.Opened == CommuncationState.Opened
You want to use & (AND) instead.
We ran into a similar problem in our own system; disconnecting the network cable or placing either the client machine or the server in sleep mode does not generate a channel fault.
From what I can tell, it seems that the connection state only indicates the state of the connection after the last call and not the current connection state. The only way to know the current state is to actually call the service.
If your client doesn’t need to call the service that often but must react if the connection is lost one solution is to implement a dummy call on the client side which periodically polls the service. If the connection is unavailable when the dummy call is made you’ll get a channel fault that you can then deal with.
The catch is you can’t simply use the dummy call to guarantee that the next call to the service will work:
public void SomeMethode()
{
if (ConnectionIsOpen())
{
m_Service.Dummy();
// Connection is lost here
m_Service.SomeMethode();
}
}
To get around this problem, we implemented a system that automatically re-executes any failed service calls which generate a channel fault after the connection has been restored.
The best and asured way to confirm the Communication state is Open or not is to call the Faulted event like below :
proxyInstance.InnerChannel.Faulted -= new EventHandler(ProxyChannelFaulted);
But this works only with those bindings that support ReliableMessaging like WsHttpBinding.
For detail refer the link : WCF Proxy Client taking time to create, any cache or singleton solution for it
Thanks,
Jai Kumar
The fact that you are getting completely different results on windows 7 is not surprising. Microsoft completely re-engineered the TCP stack with windows vista, so the functionality is quite different from xp in the core networking functionality.
The first thing that I would do is use wireshark to see what is actually going across the wire. See if your TCP connection actually terminates when you pull the plug. Windows might be doing some kind of connection persistence / buffering in case the connection comes back quickly.
Related
I'm creating an application that will connect to WiFi automatically when the connection state is unconnected.
I used the wininet.dll for it and to used its InternetGetConnectedState() method.
However, I've encountered a problem that whenever I connect to WiFi and the Connection State is "Connecting", the InternetGetConnectedState() will return false (meaning, unconnected), and it will try to connect to WiFi again and again...
This is the code:
while (true) {
if (InternetGetConnectedState(out ConState,0))
{
(do something else)
}
else
{
(connect to wifi)
}
}
Is there any other method available to know the state of connection or should i wait using the same method until the state is changed? Any help will be appreciated.
I may have it wrong, but in the reference to the wininet.dll it's stated: "(InternetGetConnectedState) Returns TRUE if there is an active modem or a LAN Internet connection, or FALSE if there is no Internet connection", see source. I think it's possible that this dll is not able to recognize the wifi network. Otherwise, the statement would have included "router" in it's explanation. You can call the GetLastError function to get additional information.
Network List Manager gives all information about network states. You can take a look on its features using this demo code (there is exe in Release folder).
A. Description
I am using ZeroMQ monitor and I find that it works when logic disconnection but does not work when network broken down (unplug my cable).
For example:
I launch client app on an android pad, then launch a server app on my windows laptop. They are connected through a router with cables.
Everything will be OK with monitor if I close or open either client app or server app manually. Namely, the monitor on both sides can receive a 'Connect' or an 'Accept' and a 'Disconnect' event.
But If I unplug cable on the server side, while the client and server are connected and running, the monitors on both sides can not detect the 'Disconnect' event.
Is the monitor designed like this?
If so, are there any solutions to detect network broken down ( a cable unplug event ) except heartbeats?
If not, how to use the ZeroMQ's original monitor mechanism to solve this problem? Can a setTCPKeepAlive() interface be useful?
B. System environment
My scenario is as below.
Client
OS: Android, running on a pad, IDE: Android studio 2.3, lib:jeromq-0.4.3
// Java Code
String monitorAddr = "inproc://client.req";
ZContext ctx = new ZContext();
ZMQ.Socket clientSocket = ctx.createSocket(ZMQ.REQ);
clientSocket.monitor(monitorAddr,ZMQ.EVENT_ALL);
// Then start a montitor thread which is implemented by my own.
Server
OS: Windows 7 ( 64 bit ), running on my laptop, IDE: VS2013, lib: Clrzmq4
// C# Code
const string MonitorEndpoint = "inproc://server.rep";
var ctx = new ZContext();
var serverSocket = new ZSocket(ctx,ZSocketType.REP);
ZError error;
// Create serverSocket pair socket
if (!serverSocket.Monitor(MonitorEndpoint, ZMonitorEvents.AllEvents, out error))
{
if (error == ZError.ETERM)
return ; // Interrupted
throw new ZException(error);
}
// Create a monitor
ZMonitor _monitor = ZMonitor.Create(ctx, MonitorEndpoint);
_monitor.AllEvents += _monitor_AllEvents;
_monitor.Start();
AFAIK there is no built in heartbeat within ZeroMQ. I know there was some discussion on the topic within the ZMQ community some years ago, and that discussion may still be going on.
It is comparatively simple to incorporate your own heartbeat messaging in your application's use of ZeroMQ, especially if you use something like Google Protocol Buffers to encode different message types; the heartbeat is just another message.
Doing heartbeats in your application (rather than relying on some inbuilt mechanism) is ultimately more flexible; you can choose the heartbeat rate, you can choose what to do if the heartbeat fails, you can decide when heartbeating is important and not important, etc.
Consider heartbeats within a PUB/SUB pattern; it's a bit difficult for the ZMQ authors to decide on your behalf what connection / disconnection / connection-break events matter to you. And if they do build in a mechanism, but an application developer didn't want it, then it is a waste of bandwidth.
It's far easier for the ZMQ authors to leave that kind of application architectural issue to the application author (that's you!) to deal with.
With your specific example, an unplugged network cable simply looks (so far as any software can determine) like no traffic is flowing; it's the same as the application not sending anything. ZMQ doesn't send anything if the application hasn't sent anything.
If you look at the events that the socket monitor can report on, they're all the consequence of something flowing over the network connection, or something done to the socket by the application.
Trying to go lower than ZMQ protocol itself and access the TCP connection that specific ZeroMQ sockets use (while others do not) doesn't sound like a good idea; it would required to break encapsulation in multiple classes.
The answer #bazza gave in 2017 was entirely correct at the time.
However, newer versions of ZMQ (specifically ZMTP) include an heartbeat functionality.
Check ZMQ documentation for
socketOpt
Java functions
name
purpose
ZMQ_HEARTBEAT_IVL
get/setHeartbeatLvl()
heartbeat interval
milliseconds between ZMPT PINGs
ZMQ_HEARTBEAT_TIMEOUT
get/setHeartbeatTimeout()
local heartbeat timeout
how long the local socket waits between received packets until it considers the connection timed out
ZMQ_HEARTBEAT_TTL
get/setHeartbeatTtl()
remote heartbeat timeout
if and when remote side shall consider the connection timed out
ZMQ_HEARTBEAT_CONTEXT is still in draft state as of 2022. It is supposed to send an byte[] context with every ping.
Now, by design of ZMQ, quoting from chapter 2 of its documentation,
The network connection itself happens in the background, and ZeroMQ
will automatically reconnect if the network connection is broken
(e.g., if the peer disappears and then comes back).
Thus, answering your main question, I'd expect the monitor to give you ZMQ_EVENT_CONNECT_RETRIED / ZMQ_EVENT_CONNECTED events after the underlying connection was detected as disrupted.
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.
I use an C# Console Application to put and read messages of the MQ..
When the application starts, it connect once with the MQ and then the connection should be always upholded.
The program runs every 30 sec and check if new messages are in the queue or a database(to put them on the queue) and check the isConnected-variable if its true.
But what happen if an exception(2009 - connection broke) in the Put/Get occur? Will the isConnected automatically set to false?
Is the connection automatically disconnected or do I have to call Disconnect() in the error handling?
Thanks!
To answer your exact question, for a basic .net application (non XMS) using MQQueue for put/get, if you get CERTAIN bad return codes from the underlying API call which indicates a connection issue, MQ will attempt an MQBACK and an MQDISC for you and will result in the connection handle being invalidated (IsConnected would return false) and an exception being thrown. However if an exception occurs outside those return codes then no attempt is made to do anything with the connection.
Basically you should not code an application relying on this behaviour, when the most simple answer is to always disconnect if you get an exception which relates to the quality of the connection or queue manager. For example, a no message available etc type exception doesnt mean you need to disconnect but a connection broken obviously does. There is no harm in calling disconnect on an already disconnected connection.
The problem
I have a .NET Client application that makes use of HubConnectionManager to retry connecting to the server if my app changes to the Closed state.
It seems to work great in the following instances:
For short disconnects (e.g. restarting the SignalR server) it immediately reconnects and picks up where it left off.
For longer disconnects (if the server is down for more than 30 seconds), it will go from connected->reconnecting->disconnected and then connect again just fine.
HOWEVER, in case (2), while the client has successfully reconnected, none of the events that the client previously subscribed to come through anymore. So, in effect, the client is connected but effectively dead.
What I've Tried
So reconnecting works in all cases, but if I reconnect after a disconnect I lose my subscriptions.
Therefore, I initially tried to capture the StateChanged event and, upon changing from Connecting to Connected, re-subscribe to the server's broadcasts (e.g. _hubProxy.On<MachineStatusDto>(UPDATE_MACHINE_STATUS, BroadcastMachineStatus);). However, this doesn't appear to work and I am concerned that, if I am not careful, I could create memory leaks just like subscribing using += multiple times.
Not sure where to go from here...
Misc. Details
The client is WPF (.NET 4 compatible)
The server is a Windows Service self-hosting SignalR (skys-the-limit .NET 4.5.2)
Client and Server are in the same building, infinite retry on connections is A-OK.
This is for an internal LoB app, so broad use across the internet and such isn't a requirement
After further investigation, and running my own Client/Server on HubConnectionManager, I realized that I am actually reconnecting and receiving subscriptions afterwards.
The caveat with my LoB application is that my subscriptions are based on a Group membership. According to MSDN:
"When reconnecting after a temporary disruption, the user
automatically re-joins the previously-assigned groups. Automatically
rejoining a group only applies when reconnecting, not when
establishing a new connection."
Therefore, I was reconnecting successfully and would have received any global messages sent by the server. However, I have to re-add my clients to their respective Group when re-establishing a connection after a DisconnectTimeout.
Here's the code I use:
//Somewhere when initializing the connection
_hubConnectionManager.StateChanged += OnHubConnectionManagerOnStateChanged;
//Handler for state change
private void OnHubConnectionManagerOnStateChanged(StateChange st)
{
//When disconnected, set state variable
if (st.NewState == ConnectionState.Disconnected)
{
_wasDisconnected = true;
}
//If disconnected and we re-create connection successfully, re-subscribe to updates.
if (_wasDisconnected && st.OldState == ConnectionState.Connecting && st.NewState == ConnectionState.Connected)
{
SubscribeToMachine(MachineStatusDetails.MachineId);
}
Messenger.Default.Send<ConnectionState>(st.NewState, UIMessageToken.ConnectionState);
}