C#Modbus / tcp - 挂连接

时间:2014-01-03 11:23:35

标签: c# tcp tcpclient modbus

我已经编写了Windows服务,它每隔10分钟使用NModbus库对三方设备执行Modbus WriteMultipleRegisters函数调用(System.Threading.Timer的滴答)。

有时,此连接会在网络问题期间挂起。由于设备一次只接受一个Modbus连接而其他设备被拒绝,因此在所有下一个滴答期间的连接都会因SocketException - ConnectionRefused而失败。

但设备会自动关闭短时间内无响应的连接。即使是两天,也必须保持连接在我身边。当我的服务重新启动时,一切都很好。所以肯定有一些被遗忘的开放联系。但是我没有设法在dev中重现这个bug,所以我不会在哪里/何时连接挂断。我只知道下次连接被拒绝了。

我用这部分代码进行modbus函数调用:

using (TcpClient client = new TcpClient(device.ip, 502))
    {
    using (Modbus.Device.ModbusIpMaster master = Modbus.Device.ModbusIpMaster.CreateIp(client))
          {
          master.WriteMultipleRegisters(500, new ushort[] { 0xFF80 });
    }  
}

device.ip是包含设备IP地址的字符串 - 它是正确的,从SocketException详细信息确认。

当我使用using语句时,会在两个对象上调用dispose。 我看过NModbus源代码,一切都正确处理。

知道如何通过此代码连接关闭它?

3 个答案:

答案 0 :(得分:3)

我同意nemec。如果您没有明确提及关闭连接,请查看TcpClient.Dispose的文档。它默认释放托管和非托管资源,但可能无法正确拆除连接。

尝试将代码更改为:

using (TcpClient client = new TcpClient(device.ip, 502))
{
    try 
    {
        using (Modbus.Device.ModbusIpMaster master = Modbus.Device.ModbusIpMaster.CreateIp(client))
        {
            master.WriteMultipleRegisters(500, new ushort[] { 0xFF80 });
        }
    }
    catch(Exception e) 
    {
        // Log exception
    }
    finally 
    {
        client.Close();
    }
}

这样你在处理之前就做了一个干净的关闭,即使Modbus协议抛出某种异常,它也应该清理。

答案 1 :(得分:2)

您是否使用TcpClient.LingerState属性

默认设置可能会导致重置winsock时出现问题

检查出来 http://msdn.microsoft.com/pl-pl/library/system.net.sockets.tcpclient.lingerstate%28v=vs.110%29.aspx

答案 2 :(得分:1)

这不是答案,而是代码注释。我们在某些已安装的计算机上遇到了同样的问题,但并非所有计算机都存在问题。问题本身也是非常间歇性的,有时几个月没有发生。我希望有人能找到答案。这是我们的强力销毁/重新连接代码不起作用

        try
        {
            try
            {
                try
                {
                    // Close the stream
                    var stream = _tcpClient.GetStream();
                    if (stream != null)
                        stream.Close();
                }
                catch { }

                try
                {
                    // Close the socket
                    if (_tcpClient.Client != null)
                        _tcpClient.Client.Close();
                }
                catch { }

                // Close the client
                _tcpClient.Close();
                _tcpClient = null;
            }
            catch { }

            if (_device != null)
            {
                _device.Dispose();
                _device = null;
            }
        }
        catch { }

        System.Threading.Thread.Sleep(1000);
相关问题