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)); } } } }