Files
GenericTeProgramLibrary/Source/TSRealLib/HAL/Implementations/LSPS/LspsChamber/Lib/TcpClientSock.cs
2025-03-13 12:04:22 -07:00

274 lines
7.0 KiB
C#

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
{
/// <summary>
/// Class for TCP client communication
/// </summary>
internal class TcpClientSock
{
private Socket sock_;
private string remoteAddress_;
private int remotePort_;
IPEndPoint remoteEP_;
IPAddress ipAddress_ = null;
private static object _syncObj = new object();
/// <summary>
/// Constructor
/// </summary>
/// <param name="remoteAddress"></param>
/// <param name="remotePort"></param>
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);
}
/// <summary>
/// Connect to remote host
/// </summary>
/// <returns></returns>
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; }
}
}
/// <summary>
/// Disconnect from remote host
/// </summary>
/// <returns></returns>
public void Disconnect()
{
lock (_syncObj)
{
if (sock_.Connected)
{
sock_.Shutdown(SocketShutdown.Both);
sock_.Disconnect(true);
sock_.Close();
}
}
}
/// <summary>
/// Ping if remote host is alive
/// </summary>
/// <returns>true/false</returns>
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;
}
/// <summary>
/// Send Command and Get Response
/// </summary>
/// <param name="command"></param>
/// <param name="responseTimeOutMs"></param>
/// <param name="responseBufSize"></param>
/// <returns>response in ASCII format</returns>
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);
}
/// <summary>
/// Read data from the device.
/// </summary>
/// <param name="dataBuf"></param>
/// <param name="responseTimeOutMs"></param>
/// <returns>The number of bytes read</returns>
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;
}
/// <summary>
/// Write data to device.
/// </summary>
/// <param name="dataBuf"></param>
/// <returns>The number of bytes written</returns>
public int Write(byte[] dataBuf)
{
int bytesWritten = 0;
lock (_syncObj)
{
try
{
bytesWritten = sock_.Send(dataBuf);
}
catch (SocketException)
{
bytesWritten = 0;
}
}
return bytesWritten;
}
/// <summary>
/// Write data to device.
/// </summary>
/// <param name="data"></param>
/// <returns>The number of bytes written</returns>
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;
}
/// <summary>
/// Clear Hardware Receiver Buffer of residual data
/// </summary>
/// <returns>none</returns>
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);
}
}
}
}