I have a SignalR hub with an override for OnDisconnectedAsync. I have found that gracefully closing the connection on the client side - like calling close() - will trigger OnDisconnectedAsync. However, the disconnect doesn't seem to trigger when disconnecting "disgracefully".
For example; When I open the client in a tab, click onto a couple of other open tabs, then close the client tab while having another tab in focus. This does not trigger a disconnect.
This also seems to happen when disconnecting from my work's network through a VPN connection. Basically, any condition that falls outwith the normal conditions for a disconnect. It's like the server still thinks the connection is open.
I have tried to reduce the KeepAliveInterval and ClientTimeoutInterval to see if I was just being impatient, but after waiting 5 minutes after disconnecting, I'm convinced it's not firing properly.
Am I doing something wrong in my hub?
services.AddSignalR(opts => {
opts.MaximumParallelInvocationsPerClient = 10;
opts.KeepAliveInterval = TimeSpan.FromSeconds(5);
opts.ClientTimeoutInterval = TimeSpan.FromSeconds(5);
});
public override async Task OnDisconnectedAsync(Exception? exception)
{
if (exception != null)
{
Log.Error(exception.Message);
}
Log.Information("${Context.UserIdentifier} Disconnected");
...bunch of additional logic
await base.OnDisconnectedAsync(exception);
}
I have ZKTeco Biometrics device which is connected with a C# windows application using This tutorial (C# ZKTeco Biometric Device Getting Started).
It is working fine but after sometime, my application becoming failed to ping the device. As below code suggested, I am trying to ping the device after every 25 seconds.
private void TimerCheckPingAndCloseAttendanceForm() {
timerCheckPingAndCloseAttendanceForm = new Timer();
timerCheckPingAndCloseAttendanceForm.Tick += new EventHandler(CheckPingAndCloseAttendanceForm);
timerCheckPingAndCloseAttendanceForm.Interval = 25000;//25 seconds.
timerCheckPingAndCloseAttendanceForm.Start();
}
private void CheckPingAndCloseAttendanceForm(object sender, EventArgs e) {
string ipAddress = tbxDeviceIP.Text.Trim();
if (UniversalStatic.PingTheDevice(ipAddress) == false) {
//CloseAttendaceListForm();
IsDeviceConnected = false;
string infoString = "Application started on " + applicationStartDateTime.ToString() + " and ping failed on " + DateTime.Now.ToString() + " then, app closed while device ip is "+ ipAddress;
File.AppendAllText("ConnectionLog.txt", infoString + Environment.NewLine);
Application.Exit();
//timerCheckPingAndCloseAttendanceForm.Tick -= new EventHandler(CheckPingAndCloseAttendanceForm);
}
}
And when I am trying to ping the command from cmd the device show destination host is unreachable. But whenever I restart the device, the ping working fine. I don't know where is the problem? Either the network problem or its coding issue?
Note: I am doing a ping on regular time interval, because on Disconnected Event is not working. I am assuming ping failed meaning is the device has disconnected with the application.
First of all : Thank you for going through my article
You are doing it the wrong way.
Trying to ping the device after every 25 seconds is unnecessary.
The only job of the UniversalStatic.PingTheDevice method is to check if the device is presumably active, the first time you connect with the device.
If you want to check the status of the device i.e IsDeviceConnected, All you need to do is register to the device OnDisConnected event provided by the SDK.
It seems the code here at line number 57 has already done the OnDisConnected event registration for you.
All you need to do now is set your IsDeviceConnected to false when the objCZKEM_OnDisConnected method in the ZkemClient.cs class is called upon by the device itself.
Sample snippet :
In the ZkemClient.cs class file, between line number 81-84
void objCZKEM_OnDisConnected()
{
IsDeviceConnected = false; // <-- Add this line
}
Now, Every time you try to make a call to the device, All you need to do is check for the value of your IsDeviceConnected.
Not having the actual code and the hardware setup, this answer is a bit of a shot in the dark, but here goes …
Since it works initially, this is not a hardware configuration or network configuration issue. Yet it says that after a while the destination (reader) becomes unavailable. This is probably not a network keepalive issue because you are pinging every 25 sec. Looking at the code that you referenced, it shows opening a connection and hooking up callbacks, and making a call to a hardware feature.
My guess would be maybe you are opening the connection each ping and not closing the connection, then after a number of attempts the hardware jams because there are too many open connections. Just a guess. If this is the problem then to fix it, either close the connection or, better, keep the connection open and re-use it.
Alternative possibility would be that the router(s) between your code and the device are detecting too many pings and blocking the connection as a possible DOS attack. If this is the problem then to fix it, configure the router to allow the traffic.
This sounds like the device misbehaving. The error "destination host is unreachable" corresponds to an ICMP packet, same type of packet as ping but different job, being sent by your router saying "I have no idea which device has that IP". This normally happens when the device stop responding to ARP, which basically asks "who has this IP?" and expects a machine to respond "I have it" with its MAC address. The router constantly refreshes its ARP table, forgetting old values.
So when you boot the device it is 'happy', responding to ARP and responding to pings; however, something happens and it at least stops responding to ARP (probably something more wrong with it). Depending on its architecture it could be loaded down doing other stuff and unable to respond, or it could just be locked up.
Try slowing down other actions to the device (if your polling it for information other than ping, do it slower) and also see if you can get status from the device via another output (does it have a uart?).
OPTION 1
Since that restarting the device fixes your problem for a period of time, check that the IP that you are using is not in use on another device/computer/element_of_the_network.
ZKTeco devices come with the IP 192.168.1.201 configured by default. Configure a different static IP and avoid using DHCP (it´s well known that using DHCP in ZKTeco devices isn´t a good choice since they don´t refresh automatically the IP after rebooting the system or any network change).
Make sure that the IP is not in use and that nobody else will use it.
OPTION 2
Another thing that It may be the cause of your problem, is that you are using zkemkeeper in a different part of your application (or into a different application) and you are not closing the oppened connections properly... That may be blocking all network activity from the device. To close the connection just make sure that you call this sdk method after performing all the necessary actions:
sdk.Disconnect();
It looks like a code issue. While investigating UniversalStatic.PingTheDevice(ipAddress), its found that its calling System.Net.NetworkInformation.Ping.Send setting DontFragment = true. Reference: https://github.com/zaagan/BioMetrix/blob/master/BioMetrixCore/Utilities/UniversalStatic.cs#LC51. The timeout for the ping is set to 120 milli seconds. This tries to send 32 bytes of data to the given IP.
Following is the snippet taken from https://learn.microsoft.com/en-us/dotnet/api/system.net.networkinformation.ping.send?view=netframework-4.7.2 would answer the root-cause of your issue
If the DontFragment property is true and the total packet size exceeds the maximum packet size that can be transmitted by one of the routing nodes between the local and remote computers, the ICMP echo request fails. When this happens, the Status is set to PacketTooBig.
So when you restart your device, possibly, the data travelling on the network gets lost. Hence it started working till the packets reaching its limit.
Few suggestions:
Try calling System.Net.NetworkInformation.Ping.Dispose in PingTheDevice before returns
Increase the timeout from 120 milliseconds to seconds.
Increase the timerCheckPingAndCloseAttendanceForm.Interval to 1 min.
Check the return code of the System.Net.NetworkInformation.Ping.Send and find the associated failure meaning
Please share your findings if the above suggestions do not help you finding the root-cause.
you try this code for ping the device,
try
{
IPAddress ipAddress = IPAddress.Parse(ipAdd);
Ping pingSender = new Ping();
PingOptions options = new PingOptions();
options.DontFragment = true;
// Create a buffer of 32 bytes of data to be transmitted.
string data = "aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa";
byte[] buffer = Encoding.ASCII.GetBytes(data);
int timeout = 120;
PingReply reply = pingSender.Send(ipAddress, timeout, buffer, options);
if (reply.Status == IPStatus.Success)
return true;
else
{
return false;
}
}
catch (Exception)
{
return false;
}
Thanks.
I am trying to make an aSync connection to a server using TcpClient.BeginConnect, but am encountering some difficulties. This is my first time using Tcp so please bear with me.
The connection itself works fine when the server is running, i can send and receive messages without problem. However when I stop the server and try to connect to it, Tcp.BeginConnect will pretend it is actually connected to a server without returning an error, until i try to actually send data which will obviously fail.
When i use TcpClient.Connect() instead it'll return A connection attempt failed because the connected party did not properly respond after a period of time, or established connection failed because connected host has failed to respond. when no connection is established after a few seconds, letting me know the connection failed.
Is there a way to get this same behaviour with TcpClient.BeginConnect? Or am I doing something wrong myself?
i looked around and found C# BeginConnect callback is fired when not connected which is somewhat similair and the answer was that EndConnect had to be called in the callback before the socket becomes usuable, but i'm already doing that.
my code:
public static void OpenTcpASyncConnection()
{
if (client == null)
{
client = new TcpClient();
IAsyncResult connection = client.BeginConnect(serverIp, serverPort, new AsyncCallback(ASyncCallBack), client);
bool succes = connection.AsyncWaitHandle.WaitOne();//returns true
if (!succes)
{
client.Close();
client.EndConnect(connection);
throw new Exception("TcpConnection::Failed to connect.");
}
else
{
Debug.LogFormat("TcpConnection::Connecting to {0} succeeded", serverIp);
}
}
else
{
Debug.Log("TcpConnection::Client already exists");
}
}
public static void ASyncCallBack(IAsyncResult ar)
{
Debug.Log("Pre EndConnect");
client.EndConnect(ar);
Debug.Log("Post EndConnect");//this never gets called?
}
the boolean succes is true even if the server is offline (or does this always return true as long as the operation finishes?), thus i assume it thinks it is actually connected, and the Debug.Log after client.EndConnect(ar) never gets called. Not a single error gets returned.
In summary; Am I forgetting something/doing something wrong? or is this expected behaviour?
Edit: language is C# with the .net 3.5 framework. It is ment for a Unity application though i'm not inheriting from monobehaviour for this. If you require any additional information I will try to provide this.
Kind regards and thanks for your time,
Remy.
I have two console applications : client and server (server is self hosted wcf service).
multiple clients can connect to same server.
If user click X button of server console...and if number of clients connected to that server is > 0, it should not close.
I tried code available here Capture console exit C#...and changed handler as below.
private static bool Handler(CtrlType sig)
{
if (CanCloseServer())
{
exitSystem = true;
//shutdown right away so there are no lingering threads
//Environment.Exit(0);
return true;
}
return false;
}
It still closes the window (reason I think is windows close command is uninterrupted even now). Could someone tell me how can I cancel the X event please.
You can create a custom mini-console app that doesn't have a close button to run your server program. Nice snippet is found in an answer for this question.
I'm making an application that will monitor the state of another process and restart it when it stops responding, exits, or throws an error.
However, I'm having trouble to make it reliably check if the process (Being a C++ Console window) has stopped responding.
My code looks like this:
public void monitorserver()
{
while (true)
{
server.StartInfo = new ProcessStartInfo(textbox_srcdsexe.Text, startstring);
server.Start();
log("server started");
log("Monitor started.");
while (server.Responding)
{
if (server.HasExited)
{
log("server exitted, Restarting.");
break;
}
log("server is running: " + server.Responding.ToString());
Thread.Sleep(1000);
}
log("Server stopped responding, terminating..");
try
{ server.Kill(); }
catch (Exception) { }
}
}
The application I'm monitoring is Valve's Source Dedicated Server, running Garry's Mod, and I'm over stressing the physics engine to simulate it stopping responding.
However, this never triggers the process class recognizing it as 'stopped responding'.
I know there are ways to directly query the source server using their own protocol, but i'd like to keep it simple and universal (So that i can maybe use it for different applications in the future).
Any help appreciated
The Responding property indicates whether the process is running a Windows message loop which isn't hung.
As the documentation states,
If the process does not have a MainWindowHandle, this property returns true.
It is not possible to check whether an arbitrary process is doing an arbitrary thing, as you're trying to.