Sic.Framework-Nanjing-Baishi/MECF.Framework.Common/MECF/Framework/Common/Communications/AsynSocketClient.cs

378 lines
9.3 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.Sockets;
using System.Text;
using System.Threading;
using Aitex.Core.RT.Event;
using Aitex.Core.RT.Log;
using MECF.Framework.Common.Equipment;
namespace MECF.Framework.Common.Communications
{
public class AsynSocketClient : IDisposable
{
public delegate void ErrorHandler(TCPErrorEventArgs args);
public delegate void MessageHandler(string message);
public delegate void BinaryMessageHandler(byte[] message);
public class ClientStateObject
{
public Socket workSocket = null;
public static int BufferSize = 256;
public byte[] buffer = new byte[BufferSize];
public StringBuilder sb = new StringBuilder();
public ClientStateObject(int bufferSize = 256)
{
BufferSize = bufferSize;
buffer = new byte[bufferSize];
}
}
private static object _locker = new object();
private Socket _socket;
private string _ip;
private int _port;
private string _address;
private int _bufferSize = 256;
private bool _isEndConnect = false;
private bool _isAsciiMode;
public string NewLine { get; set; }
public bool NeedLog { get; set; } = true;
public bool IsConnected => _socket != null && _socket.Connected && _isEndConnect;
public bool IsHstConnected => _socket != null && IsSocketConnected(_socket);
public event ErrorHandler OnErrorHappened;
public event MessageHandler OnDataChanged;
public event BinaryMessageHandler OnBinaryDataChanged;
private bool IsSocketConnected(Socket client)
{
try
{
byte[] buffer = new byte[1];
int num = client.Send(buffer);
if (num == 1)
{
return true;
}
return false;
}
catch (SocketException ex)
{
LOG.Write(ex.Message);
return false;
}
}
public AsynSocketClient(string address, bool isAsciiMode, string newline = "\r")
{
_socket = null;
NewLine = newline;
_address = address;
_isAsciiMode = isAsciiMode;
}
public AsynSocketClient(string address, int bufferSize, string newline = "\r")
{
_socket = null;
NewLine = newline;
_address = address;
_bufferSize = bufferSize;
}
~AsynSocketClient()
{
Dispose();
}
public void Connect()
{
try
{
_ip = _address.Split(':')[0];
_port = int.Parse(_address.Split(':')[1]);
IPAddress address = IPAddress.Parse(_ip);
IPEndPoint remoteEP = new IPEndPoint(address, _port);
lock (_locker)
{
_isEndConnect = false;
Dispose();
if (NeedLog)
{
LOG.Info($"Start new socket of {_address}.", isTraceOn: false);
}
if (_socket == null)
{
_socket = new Socket(AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.Tcp);
}
_socket.BeginConnect(remoteEP, ConnectCallback, _socket);
}
}
catch (Exception ex)
{
LOG.Write(ex);
throw new Exception(ex.ToString());
}
}
public bool Poll()
{
try
{
return _socket.Poll(1, SelectMode.SelectRead);
}
catch (Exception)
{
return true;
}
}
private void ConnectCallback(IAsyncResult ar)
{
try
{
if (NeedLog)
{
LOG.Info($"ConnectCallback {_address}", isTraceOn: false);
}
Socket socket = (Socket)ar.AsyncState;
if (socket.Connected)
{
socket.EndConnect(ar);
_isEndConnect = true;
if (NeedLog)
{
LOG.Info($"EndConnect", isTraceOn: false);
}
EV.PostMessage(ModuleName.Robot.ToString(), EventEnum.TCPConnSucess, _ip, _port.ToString());
Receive(_socket);
}
}
catch (Exception ex)
{
LOG.Write(ex);
string message = $"Communication {_ip}:{_port:D} {ex}.";
LOG.Error(message);
Thread.Sleep(1000);
Connect();
}
}
private void Receive(Socket client)
{
try
{
ClientStateObject clientStateObject = new ClientStateObject(_bufferSize);
clientStateObject.workSocket = client;
client.BeginReceive(clientStateObject.buffer, 0, ClientStateObject.BufferSize, SocketFlags.None, ReceiveCallback, clientStateObject);
}
catch (Exception ex)
{
LOG.Write(ex);
string text = $"TCP连接发生错误{ex.Message}";
LOG.Error($"Communication {_ip}:{_port:D} {text}.");
this.OnErrorHappened(new TCPErrorEventArgs(text));
}
}
private void ReceiveCallback(IAsyncResult ar)
{
try
{
if (!IsConnected)
{
return;
}
ClientStateObject clientStateObject = (ClientStateObject)ar.AsyncState;
Socket workSocket = clientStateObject.workSocket;
if (workSocket == null || !workSocket.Connected)
{
return;
}
int num = workSocket.EndReceive(ar);
if (num <= 0)
{
return;
}
clientStateObject.sb.Append(Encoding.ASCII.GetString(clientStateObject.buffer, 0, num));
string @string = Encoding.ASCII.GetString(clientStateObject.buffer, 0, num);
if (!_isAsciiMode)
{
byte[] array = new byte[num];
for (int i = 0; i < num; i++)
{
array[i] = clientStateObject.buffer[i];
}
if (NeedLog)
{
LOG.Info(string.Format("Communication {0}:{1:D} receive {2}.", _ip, _port, string.Join(" ", Array.ConvertAll(array, (byte x) => x.ToString("X2")))), isTraceOn: false);
LOG.Info($"Communication {_ip}:{_port:D} receive {Encoding.ASCII.GetString(array)} in ASCII.", isTraceOn: false);
}
this.OnBinaryDataChanged(array);
clientStateObject.sb.Clear();
}
else if (clientStateObject.sb.Length > NewLine.Length && clientStateObject.sb.ToString().Substring(clientStateObject.sb.Length - NewLine.Length).Equals(NewLine))
{
string text = clientStateObject.sb.ToString();
if (NeedLog)
{
LOG.Info($"Communication {_ip}:{_port:D} receive {text.TrimEnd('\n').TrimEnd('\r')}.", isTraceOn: false);
LOG.Info(string.Format("Communication {0}:{1:D} receive {2}. in BIN", _ip, _port, string.Join(" ", Array.ConvertAll(Encoding.ASCII.GetBytes(text), (byte x) => x.ToString("X2")))), isTraceOn: false);
}
this.OnDataChanged(clientStateObject.sb.ToString());
clientStateObject.sb.Clear();
}
workSocket.BeginReceive(clientStateObject.buffer, 0, ClientStateObject.BufferSize, SocketFlags.None, ReceiveCallback, clientStateObject);
}
catch (Exception ex)
{
LOG.Write(ex);
string text2 = $"TCP Socket recevice data failed{ex.Message}";
LOG.Error($"Communication {_ip}:{_port:D} {text2}.");
this.OnErrorHappened(new TCPErrorEventArgs(text2));
}
}
public bool Write(string data)
{
try
{
lock (_locker)
{
byte[] bytes = Encoding.ASCII.GetBytes(data);
_socket.BeginSend(bytes, 0, bytes.Length, SocketFlags.None, SendCallback, _socket);
if (NeedLog)
{
LOG.Info($"Communication {_ip}:{_port:D} Send {data}.", isTraceOn: false);
string arg = string.Join(" ", Array.ConvertAll(Encoding.ASCII.GetBytes(data), (byte x) => x.ToString("X2")));
LOG.Info($"Communication {_ip}:{_port:D} Send {arg} in Bin.", isTraceOn: false);
}
}
return true;
}
catch (Exception ex)
{
LOG.Write(ex);
LOG.Info($"Communication {_ip}:{_port:D} Send {data}. failed", isTraceOn: false);
string reason = $"Send command failed:{ex.Message}";
this.OnErrorHappened(new TCPErrorEventArgs(reason));
}
return false;
}
public bool Write(byte[] byteData)
{
try
{
lock (_locker)
{
_socket.BeginSend(byteData, 0, byteData.Length, SocketFlags.None, SendCallback, _socket);
if (NeedLog)
{
string arg = string.Join(" ", Array.ConvertAll(byteData, (byte x) => x.ToString("X2")));
LOG.Info($"Communication {_ip}:{_port:D} Send {arg}.", isTraceOn: false);
LOG.Info($"Communication {_ip}:{_port:D} Send {Encoding.ASCII.GetString(byteData)} in ASCII.", isTraceOn: false);
}
}
return true;
}
catch (Exception ex)
{
LOG.Write(ex);
string arg2 = string.Join(" ", Array.ConvertAll(byteData, (byte x) => x.ToString("X2")));
LOG.Info($"Communication {_ip}:{_port:D} Send {arg2}. failed", isTraceOn: false);
string reason = $"Send command failed:{ex.Message}";
this.OnErrorHappened(new TCPErrorEventArgs(reason));
}
return false;
}
private void SendCallback(IAsyncResult ar)
{
try
{
Socket socket = (Socket)ar.AsyncState;
int num = socket.EndSend(ar);
}
catch (Exception ex)
{
LOG.Write(ex);
string reason = $"Send command failed:{ex.Message}";
this.OnErrorHappened(new TCPErrorEventArgs(reason));
}
}
public void Dispose()
{
try
{
if (_socket != null)
{
if (NeedLog)
{
LOG.Info($"Dispose current socket of {_address}", isTraceOn: false);
}
if (IsConnected)
{
_socket.Shutdown(SocketShutdown.Both);
}
_socket.Close();
_socket.Dispose();
_socket = null;
}
}
catch (Exception ex)
{
LOG.Write(ex);
string reason = $"释放socket资源失败:{ex.Message}";
this.OnErrorHappened(new TCPErrorEventArgs(reason));
}
}
public void Close()
{
try
{
if (_socket != null)
{
if (NeedLog)
{
LOG.Info($"Close current socket of {_address}", isTraceOn: false);
}
if (IsConnected)
{
_socket.Shutdown(SocketShutdown.Both);
}
_socket.Close();
}
}
catch (Exception ex)
{
LOG.Write(ex);
string reason = $"Close socket资源失败:{ex.Message}";
this.OnErrorHappened(new TCPErrorEventArgs(reason));
}
}
}
}