From ac19f913af02496e802152d1e7564990ab73645a Mon Sep 17 00:00:00 2001 From: "Thomas.Bargetz" Date: Fri, 11 Aug 2017 11:09:35 +0200 Subject: [PATCH] fixed #87 IsAvailable is not using the Ping class anymore. --- S7.Net.UnitTest/S7NetTests.cs | 21 +++++++++ S7.Net/PLC.cs | 80 +++++++++++++++++++---------------- 2 files changed, 64 insertions(+), 37 deletions(-) diff --git a/S7.Net.UnitTest/S7NetTests.cs b/S7.Net.UnitTest/S7NetTests.cs index c70a687..37d1ae8 100644 --- a/S7.Net.UnitTest/S7NetTests.cs +++ b/S7.Net.UnitTest/S7NetTests.cs @@ -736,6 +736,27 @@ namespace S7.Net.UnitTest Assert.AreEqual(tc.CustomTypes[1].Bools[1], tc2.CustomTypes[1].Bools[1]); } + [TestMethod] + public void T24_IsAvailableReturnsFalseIfIPAddressIsNotReachable() + { + plc.Close(); + S7TestServer.Stop(); + + var unreachablePlc = new Plc(CpuType.S7300, "255.255.255.255", 0, 2); + Assert.IsFalse(unreachablePlc.IsAvailable); + } + + [TestMethod] + public void T25_IsAvailableReturnsTrueIfIPAddressIsReachable() + { + plc.Close(); + S7TestServer.Stop(); + S7TestServer.Start(); + + var reachablePlc = new Plc(CpuType.S7300, "127.0.0.1", 0, 2); + Assert.IsTrue(reachablePlc.IsAvailable); + } + #endregion #region Private methods diff --git a/S7.Net/PLC.cs b/S7.Net/PLC.cs index 196e690..d3cb95e 100644 --- a/S7.Net/PLC.cs +++ b/S7.Net/PLC.cs @@ -16,6 +16,8 @@ namespace S7.Net /// public class Plc : IDisposable { + private const int CONNECTION_TIMED_OUT_ERROR_CODE = 10060; + private Socket _mSocket; //TCP connection to device /// @@ -39,27 +41,19 @@ namespace S7.Net public Int16 Slot { get; private set; } /// - /// Pings the IP address and returns true if the result of the ping is Success. + /// Returns true if a connection to the plc can be established /// public bool IsAvailable { get { + #if NETFX_CORE return (!string.IsNullOrWhiteSpace(IP)); #else - using (Ping ping = new Ping()) + using (var socket = new Socket(AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.Tcp)) { - PingReply result; - try - { - result = ping.Send(IP); - } - catch (PingException) - { - result = null; - } - return result != null && result.Status == IPStatus.Success; + return Connect(socket) == ErrorCode.NoError; } #endif } @@ -119,6 +113,38 @@ namespace S7.Net Slot = slot; } + private ErrorCode Connect(Socket socket) + { + try + { + IPEndPoint server = new IPEndPoint(IPAddress.Parse(IP), 102); + socket.Connect(server); + + return ErrorCode.NoError; + } + catch (SocketException sex) + { + // see https://msdn.microsoft.com/en-us/library/windows/desktop/ms740668(v=vs.85).aspx + if (sex.ErrorCode == CONNECTION_TIMED_OUT_ERROR_CODE) + { + LastErrorCode = ErrorCode.IPAddressNotAvailable; + } + else + { + LastErrorCode = ErrorCode.ConnectionError; + } + + LastErrorString = sex.Message; + } + catch (Exception ex) + { + LastErrorCode = ErrorCode.ConnectionError; + LastErrorString = ex.Message; + } + + return LastErrorCode; + } + /// /// Open a socket and connects to the plc, sending all the corrected package and returning if the connection was successful (ErroreCode.NoError) of it was wrong. /// @@ -127,33 +153,13 @@ namespace S7.Net { byte[] bReceive = new byte[256]; - try - { - // check if available - if (!IsAvailable) - { - throw new Exception(); - } - } - catch - { - LastErrorCode = ErrorCode.IPAddressNotAvailable; - LastErrorString = string.Format("Destination IP-Address '{0}' is not available!", IP); - return LastErrorCode; - } + _mSocket = new Socket(AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.Tcp); + _mSocket.SetSocketOption(SocketOptionLevel.Socket, SocketOptionName.ReceiveTimeout, 1000); + _mSocket.SetSocketOption(SocketOptionLevel.Socket, SocketOptionName.SendTimeout, 1000); - try + if (Connect(_mSocket) != ErrorCode.NoError) { - _mSocket = new Socket(AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.Tcp); - _mSocket.SetSocketOption(SocketOptionLevel.Socket, SocketOptionName.ReceiveTimeout, 1000); - _mSocket.SetSocketOption(SocketOptionLevel.Socket, SocketOptionName.SendTimeout, 1000); - IPEndPoint server = new IPEndPoint(IPAddress.Parse(IP), 102); - _mSocket.Connect(server); - } - catch (Exception ex) { - LastErrorCode = ErrorCode.ConnectionError; - LastErrorString = ex.Message; - return ErrorCode.ConnectionError; + return LastErrorCode; } try