Sic.Framework-Nanjing-Baishi/MECF.Framework.RT.Equipment.../HardwareUnits/Efems/Rorzes/SocketClient.cs

352 lines
10 KiB
C#
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

using System;
using System.Net;
using System.Net.NetworkInformation;
using System.Net.Sockets;
using System.Text;
using System.Threading;
using Aitex.Core.RT.Log;
using MECF.Framework.Common.Communications;
namespace MECF.Framework.RT.EquipmentLibrary.HardwareUnits.Efems.Rorzes
{
public class SocketClient : IDisposable, IConnectable
{
public class ClientStateObject
{
// Client socket.
public Socket workSocket = null;
// Size of receive buffer.
public static int BufferSize = 256;
// Receive buffer.
public byte[] buffer = new byte[BufferSize];
// Received data string.
public StringBuilder sb = new StringBuilder();
public ClientStateObject(int bufferSize = 256)
{
BufferSize = bufferSize;
buffer = new byte[bufferSize];
}
}
public event Action<string> OnCommunicationError;
public event Action<string> OnAsciiDataReceived;
public event Action<byte[]> OnBinaryDataReceived;
public bool IsConnected { get { return (_socket != null && _socket.Connected); } }
private Socket _socket;
private int _bufferSize = 256;
private static Object _lockerSocket = new Object();
private IConnectionContext _config;
public SocketClient(IConnectionContext config)
{
_config = config;
}
~SocketClient()
{
Dispose();
}
public void Connect()
{
try
{
string ip = _config.Address.Split(':')[0];
int port = int.Parse(_config.Address.Split(':')[1]);
IPAddress ipAddress = IPAddress.Parse(ip);
IPEndPoint remoteEP = new IPEndPoint(ipAddress, port);
lock (_lockerSocket)
{
Dispose();
if (_socket == null)
{
_socket = new Socket(AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.Tcp);
}
_socket.BeginConnect(remoteEP, new AsyncCallback(ConnectCallback), _socket);
}
}
catch (Exception ex)
{
LOG.Error($"Failed connect, " + ex);
}
}
private void ConnectCallback(IAsyncResult ar)
{
try
{
Socket client = (Socket)ar.AsyncState;
if (client.Connected)
{
client.EndConnect(ar);
ClientStateObject state = new ClientStateObject(_bufferSize);
state.workSocket = _socket;
_socket.BeginReceive(state.buffer, 0, ClientStateObject.BufferSize, 0, new AsyncCallback(ReceiveCallback), state);
}
}
catch (Exception ex)
{
LOG.Error($"Failed connect, " + ex);
}
}
public bool Connect(out string reason)
{
Connect( );
reason = string.Empty;
return true;
}
public bool Disconnect(out string reason)
{
Dispose();
reason = string.Empty;
return true;
}
public bool CheckIsConnected()
{
if (!IsConnected)
return false;
lock (_lockerSocket)
{
if ((_socket.Poll(0, SelectMode.SelectWrite)) && (!_socket.Poll(0, SelectMode.SelectError)))
{
//byte[] buffer = new byte[1];
//_socket.ReceiveTimeout
//if (_socket.Receive(buffer, SocketFlags.Peek) == 0)
//{
// return false;
//}
//else
//{
return true;
//}
}
else
{
return false;
}
}
}
public bool SendBinaryData(byte[] data)
{
try
{
lock (_lockerSocket)
{
_socket.BeginSend(data, 0, data.Length, 0, new AsyncCallback(SendCallback), _socket);
if (_config.EnableLog)
{
LOG.Info($"Communication {_config.Address} Send {string.Join(" ", data)}." );
}
}
return true;
}
catch (Exception ex)
{
LOG.Info($"Failed send {string.Join(" ", data)}, " + ex);
NotifyError(ex.Message);
}
return false;
}
public bool SendAsciiData(string data)
{
try
{
lock (_lockerSocket)
{
byte[] byteData = Encoding.ASCII.GetBytes(data);
_socket.BeginSend(byteData, 0, byteData.Length, 0, new AsyncCallback(SendCallback), _socket);
if (_config.EnableLog)
{
LOG.Info($"Communication {_config.Address} Send {string.Join(" ", data)}.");
}
}
return true;
}
catch (Exception ex)
{
LOG.Info($"Failed send {string.Join(" ", data)}, " + ex);
NotifyError(ex.Message);
}
return false;
}
private void ReceiveCallback(IAsyncResult ar)
{
try
{
if (!IsConnected)
{
return;
}
ClientStateObject state = (ClientStateObject)ar.AsyncState;
Socket client = state.workSocket;
int bytesRead = client.EndReceive(ar);
if (bytesRead > 0)
{
string receiveMessage = Encoding.ASCII.GetString(state.buffer, 0, bytesRead);
state.sb.Append(receiveMessage);
if (!_config.IsAscii)
{
byte[] recvBuff = new byte[bytesRead];
for (int i = 0; i < bytesRead; i++)
{
recvBuff[i] = state.buffer[i];
}
if (_config.EnableLog)
{
LOG.Info($"Communication {_config.Address} receive {string.Join(" ", recvBuff)}.");
}
if (OnBinaryDataReceived != null)
{
OnBinaryDataReceived(recvBuff);
}
state.sb.Clear();
}
else if (state.sb.Length > _config.NewLine.Length)
{
if (state.sb.ToString().Substring(state.sb.Length - _config.NewLine.Length).Equals(_config.NewLine))
{
string msg = state.sb.ToString();
if (_config.EnableLog)
{
LOG.Info($"Communication {_config.Address} receive {msg}.");
}
if (OnAsciiDataReceived != null)
{
OnAsciiDataReceived(state.sb.ToString());
}
state.sb.Clear();
}
}
// Get the rest of the data.
client.BeginReceive(state.buffer, 0, ClientStateObject.BufferSize, 0, new AsyncCallback(ReceiveCallback), state);
}
}
catch (Exception ex)
{
LOG.Info($"Failed receive data, " + ex);
NotifyError(ex.Message);
}
}
private void SendCallback(IAsyncResult ar)
{
try
{
// Retrieve the socket from the state object.
Socket client = (Socket)ar.AsyncState;
// Complete sending the data to the remote device.
int bytesSent = client.EndSend(ar);
}
catch (Exception ex)
{
LOG.Info($"Failed send data, " + ex);
NotifyError(ex.Message);
}
}
/// <summary>
/// 释放资源Dispose
/// </summary>
public void Dispose()
{
try
{
if (_socket != null)
{
if (IsConnected)
{
_socket.Shutdown(SocketShutdown.Both);
}
_socket.Close();
_socket.Dispose();
_socket = null;
}
}
catch (Exception ex)
{
LOG.Write($"Dispose {_config.Address} resource exception, {ex}");
}
}
private void NotifyError(string reason)
{
if (OnCommunicationError != null)
OnCommunicationError(reason);
}
private bool PingConnect()
{
bool result = true;
if (_socket != null && _socket.Connected)
{
try
{
Ping pingTest = new Ping();
PingReply reply = pingTest.Send(_config.Address.Split(':')[0]);
if (reply.Status != IPStatus.Success)
result = false;
}
catch (PingException) { result = false; }
if (_socket.Poll(1000, SelectMode.SelectRead) && (_socket.Available == 0))
{
result = false;
}
}
else
{
result = false;
}
return result;
}
}
}