UnlawfulCitizen / nmodbus

Automatically exported from code.google.com/p/nmodbus
0 stars 0 forks source link

InvalidOperationException on network failure #50

Open GoogleCodeExporter opened 9 years ago

GoogleCodeExporter commented 9 years ago
What steps will reproduce the problem?
1. All working fine --> data is retrieved from deivce, then...
2. The netowrk is disconnected (Unplug the network cable...)
3. A read attempt to the device fails --> As expected
4. The network is reconnected
5. A read attempt throughs the following exception:  
   InvalidOperationException - The operation is not allowed on non-
connected sockets.

Running Windows XP, VS2008, NModbus_net-3[1].5_1.11.0.0.

I am using ModbusIpMaster to connect and retrieve data from an modbus 
(TCP) enabled device.
This works fine, until the a network clitch ouccurs (Net work cable is 
unplugged).
The next call after the netork has been re-established throughs the 
following exception:
InvalidOperationException - The operation is not allowed on non-connected 
sockets.

Although I can catch the exception I cannot get "reconnected".

Any ideas on how to re-establish the connection?

Ocle

Original issue reported on code.google.com by e...@drpa.co.za on 29 Oct 2009 at 8:58

GoogleCodeExporter commented 9 years ago
Hi,

please have a look at the:

http://groups.google.com/group/nmodbus-discuss/browse_thread/thread/4dbf37e02e70
9e95

Kind regards,

David

Original comment by david.ba...@gmail.com on 7 Jan 2010 at 3:48

GoogleCodeExporter commented 9 years ago
as alternative you may implement Modbus.IO.IStreamResource which will reconnect 
on failure.

Sample unchecked code:
{{{
    public class SafeNetworkStream : Modbus.IO.IStreamResource, IDisposable
    {
        private TcpClient tcp = null; // internal tcp client
        private Uri target = null; // tcp://1.2.3.4:502/
        private int _rt = 500; // read timeout
        private int _wt = 1000; // write timeout

        public SafeNetworkStream(Uri target)
        {
            this.target = target;
            Connect();
        }

        public void Dispose()
        {
            var t = tcp;
            tcp = null;
            if (t != null)
                try
                {
                    t.Close();
                }
                catch { }
        }

        public void DiscardInBuffer()
        {
            var t = tcp;
            if(t != null)
                try
                {
                    if (!t.Connected) return;
                    var s = t.GetStream();
                    int a;
                    while ((a = t.Available) > 0)
                        s.Read(new byte[a], 0, a); // HACK
                }
                catch { }
        }

        public int InfiniteTimeout { get { return Timeout.Infinite; } }

        public int ReadTimeout
        {
            get { return _rt; }
            set 
            {
                _rt = value;
                if (tcp != null) tcp.ReceiveTimeout = _rt;
            }
        }

        public int WriteTimeout
        {
            get { return _wt; }
            set
            {
                _wt = value;               
                if (tcp != null) tcp.SendTimeout = _wt;
            }
        }

        private void Connect()
        {
            if(Monitor.TryEnter(target))
                try
                {
                    var t = tcp;
                    tcp = null;
                    ThreadPool.QueueUserWorkItem(_connect);
                    if (t != null) t.Close();
                }
                catch { }
                finally { Monitor.Exit(target); }
        }

        object _connectLock = new object();

        private void _connect(object e)
        {
            if(Monitor.TryEnter(_connectLock))
                try
                {
                    int port = target.Port;
                    var t = new TcpClient(target.Host, port <= 0 ? 502 : port)
                        {
                            ReceiveBufferSize = 10000,
                            ReceiveTimeout = _rt,
                            SendTimeout = _wt
                        };
                    if (t.Connected) tcp = t;
                }
                catch { }
                finally { Monitor.Exit(_connectLock); }
        }

        public int Read(byte[] buffer, int offset, int count)
        {
            var t = tcp;
            if (t != null)
                try
                {
                    return t.GetStream().Read(buffer, offset, count);
                }
                catch { }
                Connect();
            return -1;
        }

        public void Write(byte[] buf, int ofs, int cnt)
        {
            var t = tcp;
            if(t != null)
                try
                {
                    t.GetStream().Write(buf, ofs, cnt);
                    return;
                }
                catch { }
            Connect();
        }

    }
}}}

Original comment by unejir...@gmail.com on 27 Jul 2010 at 6:16