using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Net.Sockets;
using System.Net;
using Aitex.Sorter.Common;
using Aitex.Core.RT.Log;
using Aitex.Core.RT.Event;
using System.Configuration;
using MECF.Framework.Common.Equipment;
using System.Threading;
namespace MECF.Framework.RT.EquipmentLibrary.HardwareUnits.Robot
{
public enum DataType
{
Ascii,
Byte
}
public class AsyncSocket : ICommunication, IDisposable
{
public delegate void ErrorHandler(ErrorEventArgs args);
public event ErrorHandler OnErrorHappened;
public delegate void MessageHandler(string message);
public event MessageHandler OnDataChanged;
public delegate void BufferDataHander(byte[] data);
public event BufferDataHander OnBufferDataReceived;
public delegate void ConnectHandler();
public event ConnectHandler OnConnect;
private static Object _locker = new Object();
public class ClientStateObject
{
// Client socket.
public Socket workSocket = null;
// Size of receive buffer.
public const int BufferSize = 8192;
// Receive buffer.
public byte[] buffer = new byte[BufferSize];
// Received data string.
public StringBuilder sb = new StringBuilder();
}
private string _newLine { get; set; }
private Socket _socket;
private string _ip;
private int _port;
private DataType _dataType;
private bool _supportReconnect = false;
private int _reconnectInterval = 3000;
private object _reconnectLocker = new object();
private Thread _reconnectThread = null;
public bool IsConnected { get { return (_socket != null && _socket.Connected); } }
public AsyncSocket(string address, string newline ="\r",DataType dataType=DataType.Ascii,bool supportReconnect=false)
{
// Connect(address);
_socket = null;
_newLine = newline;
_supportReconnect = supportReconnect;
_dataType = dataType;
}
~AsyncSocket()
{
Dispose();
}
public void Connect(string address)
{
_ip =address.Split(':')[0];
_port =int.Parse(address.Split(':')[1]);
try
{
Connect();
}
catch
{
}
}
///
/// 连接
///
///
private void Connect()
{
try
{
IPAddress ipAddress = IPAddress.Parse(_ip);
IPEndPoint remoteEP = new IPEndPoint(ipAddress, _port);
_socket = new Socket(AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.Tcp);
_socket.ReceiveTimeout = 2000;
_socket.SendTimeout = 2000;
// Connect to the remote endpoint.
_socket.BeginConnect(remoteEP, new AsyncCallback(ConnectCallback), _socket);
}
catch (Exception e)
{
if (!_supportReconnect)
{
throw new Exception(e.ToString());
}
else
{
StartReconnectThread();
}
}
}
///
/// 启动重新连接线程
///
private void StartReconnectThread()
{
lock (_reconnectLocker)
{
if (_reconnectThread==null)
{
_reconnectThread = new Thread(ReConnectThread);
_reconnectThread.IsBackground = true;
_reconnectThread.Start();
}
}
}
///
/// 重新连接线程
///
private void ReConnectThread()
{
//休眠一定时间后再连接
Thread.Sleep(_reconnectInterval);
try
{
Connect();
}
catch
{
}
_reconnectThread = null;
}
///
/// 连接回调函数
///
///
private void ConnectCallback(IAsyncResult ar)
{
try
{
// Retrieve the socket from the state object.
Socket client = (Socket)ar.AsyncState;
// Complete the connection.
client.EndConnect(ar);
if(OnConnect!=null)
{
OnConnect();
}
// Receive the response from the remote device.
Receive(_socket);
}
catch(Exception e)
{
string reason = string.Format("Communication {0}:{1:D} {2}.", _ip, _port, e.Message);
OnErrorHappened(new ErrorEventArgs(reason));
if (_supportReconnect)
{
StartReconnectThread();
}
}
}
///
/// 异步接收数据
///
///
private void Receive(Socket client)
{
try
{
// Create the state object.
ClientStateObject state = new ClientStateObject();
state.workSocket = client;
// Begin receiving the data from the remote device.
client.BeginReceive(state.buffer, 0, ClientStateObject.BufferSize, 0, new AsyncCallback(ReceiveCallback), state);
}
catch (Exception e)
{
string reason = string.Format("TCP connect failed:{0}", e.Message);
OnErrorHappened(new ErrorEventArgs(reason));
if (_supportReconnect)
{
StartReconnectThread();
}
}
}
///
/// 接收数据回调数据
///
///
private void ReceiveCallback(IAsyncResult ar)
{
try
{
if (!IsConnected) { return; }
// Retrieve the state object and the client socket
// from the asynchronous state object.
ClientStateObject state = (ClientStateObject)ar.AsyncState;
Socket client = state.workSocket;
// Read data from the remote device.
int bytesRead = client.EndReceive(ar);
if (bytesRead > 0)
{
// There might be more data, so store the data received so far.
if (_dataType == DataType.Ascii)
{
state.sb.Append(Encoding.ASCII.GetString(state.buffer, 0, bytesRead));
if (state.sb.Length > _newLine.Length)
{
if (state.sb.ToString().Substring(state.sb.Length - _newLine.Length).Equals(_newLine))
{
string msg = state.sb.ToString();
if (OnDataChanged != null)
{
OnDataChanged(state.sb.ToString());
}
state.sb.Clear();
}
}
}
else
{
if(OnBufferDataReceived!=null)
{
OnBufferDataReceived(state.buffer);
}
}
// Get the rest of the data.
client.BeginReceive(state.buffer, 0, ClientStateObject.BufferSize, 0, new AsyncCallback(ReceiveCallback), state);
}
}
catch (Exception ex)
{
LOG.WriteExeption(ex);
string reason = string.Format("TCP Socket recevice data failed:{0}", ex.Message);
OnErrorHappened(new ErrorEventArgs(reason));
if (_supportReconnect)
{
StartReconnectThread();
}
}
}
///
/// 写数据
///
///
///
public bool Write(string data)
{
if(_socket==null||!_socket.Connected)
{
return false;
}
try
{
lock (_locker)
{
// Convert the string data to byte data using ASCII encoding.
byte[] byteData = Encoding.ASCII.GetBytes(data);
_socket.BeginSend(byteData, 0, byteData.Length, 0, new AsyncCallback(SendCallback), _socket);
}
return true;
}
catch (Exception ex)
{
LOG.WriteExeption(ex);
string reason = string.Format("Send command failed:{0}", ex.Message);
OnErrorHappened(new ErrorEventArgs(reason));
if (_supportReconnect)
{
StartReconnectThread();
}
}
return false;
}
///
/// 写入二进制数据
///
///
///
public bool Write(byte[] byteData)
{
if (_socket == null || !_socket.Connected)
{
return false;
}
try
{
lock (_locker)
{
_socket.BeginSend(byteData, 0, byteData.Length, 0, new AsyncCallback(SendCallback), _socket);
}
return true;
}
catch (Exception ex)
{
LOG.WriteExeption(ex);
string reason = string.Format("Send command failed:{0}", ex.Message);
OnErrorHappened(new ErrorEventArgs(reason));
if(_supportReconnect)
{
StartReconnectThread();
}
}
return false;
}
///
/// 发送数据回调函数
///
///
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.WriteExeption(ex);
string reason = string.Format("Send command failed:{0}", ex.Message);
OnErrorHappened(new ErrorEventArgs(reason));
if (_supportReconnect)
{
StartReconnectThread();
}
}
}
///
/// 释放资源(Dispose)
///
public void Dispose()
{
try
{
if (_socket != null)
{
if (IsConnected)
{
_socket.Shutdown(SocketShutdown.Both);
}
_socket.Close();
_socket.Dispose();
_socket = null;
_supportReconnect = false;
}
}
catch (Exception ex)
{
LOG.WriteExeption(ex);
string reason = string.Format("释放socket资源失败:{0}", ex.Message);
OnErrorHappened(new ErrorEventArgs(reason));
}
}
}
}