生物识别设备ping有时会失败

时间:2018-11-28 10:00:19

标签: c# connection biometrics zkteco zkemkeeper

我有 ZKTeco 生物识别设备,该设备使用This tutorial (C# ZKTeco Biometric Device Getting Started)与C#Windows应用程序连接。

它工作正常,但是一段时间后,我的应用程序无法ping设备。如以下代码所示,我尝试每隔25秒对设备进行一次ping操作。

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

,当我尝试从cmd ping命令时,设备显示destination host is unreachable 。但是,每当我重新启动设备时,Ping都能正常运行。我不知道问题出在哪里?是网络问题还是其编码问题?

注意:我正在按固定的时间间隔执行ping操作,因为on Disconnected Event is not working。我假设ping操作失败是因为设备已与应用程序断开连接。

6 个答案:

答案 0 :(得分:1)

首先::谢谢您浏览我的文章

您做错了方法。

每25秒尝试ping设备一次是不必要的。

UniversalStatic.PingTheDevice 方法的唯一工作是在您首次连接设备时检查设备是否大概处于活动状态

如果要检查设备的状态 ie IsDeviceConnected,只需注册SDK提供的设备 OnDisConnected 事件

第57行的the code here似乎已经为您完成了 OnDisConnected 事件注册。

当设备本身调用ZkemClient.cs类中的 objCZKEM_OnDisConnected 方法时,现在要做的只是将 IsDeviceConnected 设置为false。

示例片段: 在ZkemClient.cs类文件中,行号81-84之间

void objCZKEM_OnDisConnected()
{
     IsDeviceConnected = false;  // <-- Add this line
}

现在,每次尝试拨打该设备时,您要做的就是检查 IsDeviceConnected 的值。

答案 1 :(得分:0)

由于没有实际的代码和硬件设置,这个答案有点笼罩在黑暗中,但是在这里……

因为它最初可以工作,所以这不是硬件配置或网络配置问题。但它说,过一会儿目的地(阅读器)不可用。这可能不是网络保持活动状态的问题,因为您每25秒执行一次ping操作。查看您引用的代码,它显示了打开连接并连接回调,并调用了硬件功能。

我的猜测是,您可能会在每次ping操作时打开连接,而不是关闭连接,然后经过多次尝试后,由于打开的连接过多,导致硬件阻塞。只是一个猜测。如果这是问题所在,则要修复它,请关闭连接,或者最好保持连接打开并重新使用。

另一种可能性是,代码和设备之间的路由器检测到过多的ping并阻止了连接,这可能是DOS攻击。如果这是问题,那么要解决此问题,请将路由器配置为允许流量。

答案 2 :(得分:0)

这听起来像设备行为异常。错误“目标主机不可访问”对应于一个ICMP数据包,该数据包与ping具有相同类型的数据包,但工作不同,由您的路由器发送,说“我不知道哪个设备具有该IP”。当设备停止响应ARP时,通常会发生这种情况,而ARP基本询问“谁拥有此IP?”。并期望机器以其MAC地址响应“我拥有”。路由器会不断刷新其ARP表,而忘记了旧值。

因此,当您启动设备时,它“很高兴”,响应ARP并响应ping。但是,某些事情发生了,并且至少停止了对ARP的响应(可能是它出了点问题)。视其架构而定,它可能会被加载做其他事情而无法响应,或者可能被锁定。

尝试减慢设备的其他操作(如果您轮询它以获取除ping以外的信息,则速度会变慢),并查看是否可以通过另一个输出从设备获取状态(它是否有uart?)。

答案 3 :(得分:0)

选项1

由于重新启动设备会在一段时间内解决您的问题,因此请检查所使用的IP是否在另一台设备/计算机/ element_of_the_network上未被使用。

ZKTeco设备默认配置IP 192.168.1.201。配置不同的静态IP并避免使用DHCP (众所周知,在ZKTeco设备中使用DHCP是一个不错的选择,因为它们在重新启动系统或进行任何网络更改后不会自动刷新IP )。

确保未使用IP,并且没有其他人会使用它。

选项2

另一可能是导致问题的原因是,您在应用程序的不同部分(或在不同的应用程序中)使用了zkemkeeper,而您没有正确关闭相应的连接...这可能是阻止该设备的所有网络活动。要关闭连接,只需确保在执行所有必要的操作后调用此sdk方法:

sdk.Disconnect();

答案 4 :(得分:0)

它看起来像是一个代码问题。在调查UniversalStatic.PingTheDevice(ipAddress)时,它发现其调用System.Net.NetworkInformation.Ping.Send的设置DontFragment = true。参考:https://github.com/zaagan/BioMetrix/blob/master/BioMetrixCore/Utilities/UniversalStatic.cs#LC51。 ping的超时设置为120毫秒。这样会尝试将32个字节的数据发送到给定的IP。

以下是摘自https://docs.microsoft.com/en-us/dotnet/api/system.net.networkinformation.ping.send?view=netframework-4.7.2的摘要,它将回答您问题的根本原因

  

如果DontFragment属性为true,并且总数据包大小超过了本地计算机和远程计算机之间的路由节点之一可以传输的最大数据包大小,则ICMP回显请求将失败。发生这种情况时,状态将设置为PacketTooBig。

因此,当您重新启动设备时,可能会丢失网络上传输的数据。因此它开始工作,直到数据包达到极限为止。

一些建议:

  • 尝试在返回之前在PingTheDevice中调用System.Net.NetworkInformation.Ping.Dispose
  • 将超时从120毫秒增加到秒。
  • 将timerCheckPingAndCloseAttendanceForm.Interval增加到1分钟。
  • 检查System.Net.NetworkInformation.Ping.Send的返回码,并找到相关的故障含义

如果上述建议不能帮助您找到根本原因,请分享您的发现。

答案 5 :(得分:0)

您尝试使用此代码对设备执行ping操作

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

谢谢。