using System; using System.Collections.Generic; using System.Linq; using System.Net.NetworkInformation; using System.Net.Sockets; using System.Net; using System.Text; using System.Text.RegularExpressions; using System.Threading.Tasks; namespace Raytheon.Instruments.LSPS { /// /// Class for TCP client communication /// internal class TcpClientSock { private Socket sock_; private string remoteAddress_; private int remotePort_; IPEndPoint remoteEP_; IPAddress ipAddress_ = null; private static object _syncObj = new object(); /// /// Constructor /// /// /// public TcpClientSock(string remoteAddress, int remotePort) { remoteAddress_ = remoteAddress; remotePort_ = remotePort; // if remoteAddress is a hostname if (!IPAddress.TryParse(remoteAddress_, out ipAddress_)) { string preferredSubnet = ""; IPHostEntry host = Dns.GetHostEntry(remoteAddress_); foreach (IPAddress ip in host.AddressList) { AddressFamily af = ip.AddressFamily; if (af == AddressFamily.InterNetwork) { if (preferredSubnet != String.Empty) { if (Regex.IsMatch(ip.ToString(), preferredSubnet, RegexOptions.IgnoreCase)) ipAddress_ = ip; } else ipAddress_ = ip; if (ipAddress_ != null) break; } } } if (ipAddress_ != null) { remoteEP_ = new IPEndPoint(ipAddress_, remotePort_); } else throw new Exception("Unable to connect to " + remoteAddress_); sock_ = new Socket(ipAddress_.AddressFamily, SocketType.Stream, ProtocolType.Tcp); } /// /// Connect to remote host /// /// public void Connect() { lock (_syncObj) { try { if (!sock_.Connected && IsRemoteHostAlive()) sock_.Connect(remoteEP_); } catch (ObjectDisposedException) { sock_ = new Socket(ipAddress_.AddressFamily, SocketType.Stream, ProtocolType.Tcp); if (IsRemoteHostAlive()) sock_.Connect(remoteEP_); } catch (Exception) { throw; } } } /// /// Disconnect from remote host /// /// public void Disconnect() { lock (_syncObj) { if (sock_.Connected) { sock_.Shutdown(SocketShutdown.Both); sock_.Disconnect(true); sock_.Close(); } } } /// /// Ping if remote host is alive /// /// true/false bool IsRemoteHostAlive() { bool isRemoteHostAlive = true; //Do a ping test to see if the server is reachable try { Ping pingTest = new Ping(); PingReply reply = pingTest.Send(ipAddress_); if (reply.Status != IPStatus.Success) isRemoteHostAlive = false; } catch (PingException) { isRemoteHostAlive = false; } //See if the tcp state is ok if (sock_.Poll(5000, SelectMode.SelectRead) && (sock_.Available == 0)) { isRemoteHostAlive = false; } return isRemoteHostAlive; } /// /// Send Command and Get Response /// /// /// /// /// response in ASCII format public string SendCommandAndGetResponse(string command, int responseTimeOutMs = 5000, int responseBufSize = 1024) { byte[] bytes = new byte[responseBufSize]; sock_.ReceiveTimeout = responseTimeOutMs; int bytesRec = 0; byte[] msg = Encoding.ASCII.GetBytes(command); lock (_syncObj) { sock_.Send(msg); try { bytesRec = sock_.Receive(bytes); } catch (SocketException ex) { throw new Exception("SocketException Error Code: " + ex.ErrorCode + $" ({((SocketError)ex.ErrorCode).ToString()})"); } } return Encoding.ASCII.GetString(bytes, 0, bytesRec); } /// /// Read data from the device. /// /// /// /// The number of bytes read public int Read(ref byte[] dataBuf, int responseTimeOutMs = 5000) { int bytesRec = 0; sock_.ReceiveTimeout = responseTimeOutMs; lock (_syncObj) { try { bytesRec = sock_.Receive(dataBuf); } catch (SocketException) { bytesRec = 0; } } return bytesRec; } /// /// Write data to device. /// /// /// The number of bytes written public int Write(byte[] dataBuf) { int bytesWritten = 0; lock (_syncObj) { try { bytesWritten = sock_.Send(dataBuf); } catch (SocketException) { bytesWritten = 0; } } return bytesWritten; } /// /// Write data to device. /// /// /// The number of bytes written public int Write(string data) { int bytesWritten = 0; byte[] msg = Encoding.ASCII.GetBytes(data); lock (_syncObj) { try { bytesWritten = sock_.Send(msg); } catch (SocketException) { bytesWritten = 0; } } return bytesWritten; } /// /// Clear Hardware Receiver Buffer of residual data /// /// none public void ClearReceiveBuffer() { byte[] bytes = new byte[1024]; sock_.ReceiveTimeout = 100; int bytesRec = 0; lock (_syncObj) { do { try { bytesRec = sock_.Receive(bytes); } catch (SocketException) { bytesRec = 0; } } while (bytesRec > 0); } } } }