我已经编写了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源代码,一切都正确处理。
知道如何通过此代码连接关闭它?
答案 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);