using System; using System.Collections.Generic; using System.Linq; using System.Text; using System.Net.Sockets; using System.IO; using System.Threading; using System.Net; using System.Threading.Tasks; using Aitex.Core.RT.Log; using MECF.Framework.RT.Core; using MECF.Framework.RT.Core.IoProviders.Siemens; using MECF.Framework.RT.Core.IoProviders.Siemens.IMessage; using MECF.Framework.RT.Core.IoProviders.Siemens.Transfer; using MECF.Framework.RT.Core.IoProviders.Siemens.Net.StateOne; #if (NET451 || NETSTANDARD2_0) using System.Threading.Tasks; #endif /************************************************************************************* * * 说明: * 本组件的所有网络类的基类。提供了一些基础的操作实现,部分实现需要集成实现 * * 重构日期:2018年3月8日 21:22:05 * *************************************************************************************/ namespace MECF.Framework.RT.Core.IoProviders.Siemens.Net.NetworkBase { /// /// 本系统所有网络类的基类,该类为抽象类,无法进行实例化 /// /// /// network base class, support basic operation with socket /// public abstract class NetworkBase { #region Constructor /// /// 实例化一个NetworkBase对象 /// /// /// 令牌的默认值为空,都是0x00 /// public NetworkBase( ) { Token = Guid.Empty; } #endregion #region Public Properties /// /// 网络类的身份令牌 /// /// /// 适用于Hsl协议相关的网络通信类,不适用于设备交互类。 /// /// /// 此处以 服务器类及 客户端类的令牌设置举例 /// /// /// public Guid Token { get; set; } /// /// 是否使用同步的网络通讯 /// public bool UseSynchronousNet { get; set; } = false; #endregion #region Potect Member /// /// 通讯类的核心套接字 /// protected Socket CoreSocket = null; public bool IsConnected { get { return CoreSocket != null && CoreSocket.Connected; } } #endregion #region Protect Method /// /// 检查网络套接字是否操作超时,需要对套接字进行封装 /// /// 通常是 对象 protected void ThreadPoolCheckTimeOut( object obj ) { if (obj is HslTimeOut timeout) { while (!timeout.IsSuccessful) { System.Threading.Thread.Sleep( 100 ); if ((DateTime.Now - timeout.StartTime).TotalMilliseconds > timeout.DelayTime) { // 连接超时或是验证超时 if (!timeout.IsSuccessful) { timeout.Operator?.Invoke( ); timeout.WorkSocket?.Close( ); } break; } } } } #endregion /***************************************************************************** * * 说明: * 下面的三个模块代码指示了如何接收数据,如何发送数据,如何连接网络 * ********************************************************************************/ #region Reveive Content /// /// 接收固定长度的字节数组 /// /// /// Receive Special Length Bytes /// /// 网络通讯的套接字 /// 准备接收的数据长度 /// 包含了字节数据的结果类 protected OperateResult Receive( Socket socket, int length ) { if (length == 0) return OperateResult.CreateSuccessResult( new byte[0] ); if (UseSynchronousNet) { try { byte[] data = NetSupport.ReadBytesFromSocket( socket, length ); return OperateResult.CreateSuccessResult( data ); } catch (Exception ex) { socket?.Close( ); LOG.Write(ex, "Receive"); return new OperateResult( ex.Message ); } } OperateResult result = new OperateResult( ); ManualResetEvent receiveDone = null; StateObject state = null; try { receiveDone = new ManualResetEvent( false ); state = new StateObject( length ); } catch (Exception ex) { return new OperateResult( ex.Message ); } try { state.WaitDone = receiveDone; state.WorkSocket = socket; // Begin receiving the data from the remote device. socket.BeginReceive( state.Buffer, state.AlreadyDealLength, state.DataLength - state.AlreadyDealLength, SocketFlags.None, new AsyncCallback( ReceiveCallback ), state ); } catch (Exception ex) { // 发生了错误,直接返回 LOG.Write( ex ,ToString()); result.Message = ex.Message; receiveDone.Close( ); socket?.Close( ); return result; } // 等待接收完成,或是发生异常 receiveDone.WaitOne( ); receiveDone.Close( ); // 接收数据失败 if (state.IsError) { socket?.Close( ); result.Message = state.ErrerMsg; return result; } // 远程关闭了连接 if (state.IsClose) { // result.IsSuccess = true; result.Message = StringResources.Language.RemoteClosedConnection; socket?.Close( ); return result; } // 正常接收到数据 result.Content = state.Buffer; result.IsSuccess = true; state.Clear( ); state = null; return result; } private void ReceiveCallback( IAsyncResult ar ) { if (ar.AsyncState is StateObject state) { try { Socket client = state.WorkSocket; int bytesRead = client.EndReceive( ar ); if (bytesRead > 0) { // 接收到了数据 state.AlreadyDealLength += bytesRead; if (state.AlreadyDealLength < state.DataLength) { // 获取接下来的所有的数据 client.BeginReceive( state.Buffer, state.AlreadyDealLength, state.DataLength - state.AlreadyDealLength, SocketFlags.None, new AsyncCallback( ReceiveCallback ), state ); } else { // 接收到了所有的数据,通知接收数据的线程继续 state.WaitDone.Set( ); } } else { // 对方关闭了网络通讯 state.IsClose = true; state.WaitDone.Set( ); } } catch (Exception ex) { state.IsError = true; LOG.Write(ex, "ReceiveCallback"); state.ErrerMsg = ex.Message; state.WaitDone.Set( ); } } } #if !NET35 /// /// 接收固定长度的字节数组 /// /// /// Receive Special Length Bytes /// /// 网络通讯的套接字 /// 准备接收的数据长度 /// 包含了字节数据的结果类 protected OperateResult ReceiveAsync( Socket socket, int length ) { if (length <= 0) return OperateResult.CreateSuccessResult( new byte[0] ); var state = new StateObjectAsync( length ); state.Tcs = new TaskCompletionSource( ); state.WorkSocket = socket; try { socket.BeginReceive( state.Buffer, state.AlreadyDealLength, state.DataLength - state.AlreadyDealLength, SocketFlags.None, new AsyncCallback( ReceiveAsyncCallback ), state ); byte[] byteResult = state.Tcs.Task.Result; if (byteResult == null) { socket?.Close( ); return new OperateResult( StringResources.Language.RemoteClosedConnection ); } state.Clear( ); state = null; return OperateResult.CreateSuccessResult( byteResult ); } catch (Exception ex) { return new OperateResult( ex.Message ); } } private void ReceiveAsyncCallback( IAsyncResult ar ) { if (ar.AsyncState is StateObjectAsync state) { try { Socket socket = state.WorkSocket; int bytesRead = socket.EndReceive( ar ); if (bytesRead > 0) { // 接收到了数据 state.AlreadyDealLength += bytesRead; if (state.AlreadyDealLength < state.DataLength) { // 获取接下来的所有的数据 socket.BeginReceive( state.Buffer, state.AlreadyDealLength, state.DataLength - state.AlreadyDealLength, SocketFlags.None, new AsyncCallback( ReceiveAsyncCallback ), state ); } else { // 接收到了所有的数据,通知接收数据的线程继续 state.Tcs.SetResult( state.Buffer ); } } else { // 对方关闭了网络通讯 state.IsClose = true; state.Tcs.SetResult( null ); } } catch (Exception ex) { state.IsError = true; LOG.Write(ex, "ReceiveAsyncCallback"); state.Tcs.SetException( ex ); } } } #endif #endregion #region Receive Message /// /// 接收一条完整的 数据内容 -> /// Receive a complete data content /// /// 网络的套接字 /// 超时时间 /// 消息的格式定义 /// 带有是否成功的byte数组对象 protected OperateResult ReceiveByMessage( Socket socket, int timeOut, INetMessage netMessage ) { HslTimeOut hslTimeOut = new HslTimeOut( ) { DelayTime = timeOut, WorkSocket = socket, }; if (timeOut > 0) ThreadPool.QueueUserWorkItem( new WaitCallback( ThreadPoolCheckTimeOut ), hslTimeOut ); // 接收指令头 OperateResult headResult = Receive( socket, netMessage.ProtocolHeadBytesLength ); if (!headResult.IsSuccess) { hslTimeOut.IsSuccessful = true; return headResult; } netMessage.HeadBytes = headResult.Content; int contentLength = netMessage.GetContentLengthByHeadBytes( ); if (contentLength <= 0) { hslTimeOut.IsSuccessful = true; return headResult; } OperateResult contentResult = Receive( socket, contentLength ); if (!contentResult.IsSuccess) { hslTimeOut.IsSuccessful = true; return contentResult; } hslTimeOut.IsSuccessful = true; netMessage.ContentBytes = contentResult.Content; return OperateResult.CreateSuccessResult( SoftBasic.SpliceTwoByteArray( headResult.Content, contentResult.Content ) ); } #endregion #region Send Content /// /// 发送消息给套接字,直到完成的时候返回 /// /// 网络套接字 /// 字节数据 /// 发送是否成功的结果 protected OperateResult Send( Socket socket, byte[] data ) { if (data == null) return OperateResult.CreateSuccessResult( ); if (UseSynchronousNet) { try { socket.Send( data ); return OperateResult.CreateSuccessResult( ); } catch (Exception ex) { socket?.Close( ); LOG.Write(ex, "Send"); return new OperateResult( ex.Message ); } } OperateResult result = new OperateResult( ); ManualResetEvent sendDone = null; StateObject state = null; try { sendDone = new ManualResetEvent( false ); state = new StateObject( data.Length ); } catch (Exception ex) { return new OperateResult( ex.Message ); } try { state.WaitDone = sendDone; state.WorkSocket = socket; state.Buffer = data; socket.BeginSend( state.Buffer, state.AlreadyDealLength, state.DataLength - state.AlreadyDealLength, SocketFlags.None, new AsyncCallback( SendCallBack ), state ); } catch (Exception ex) { // 发生了错误,直接返回 LOG.Write(ex); result.Message = ex.Message; socket?.Close( ); sendDone.Close( ); return result; } // 等待发送完成 sendDone.WaitOne( ); sendDone.Close( ); if (state.IsError) { socket.Close( ); result.Message = state.ErrerMsg; return result; } state.Clear( ); state = null; result.IsSuccess = true; result.Message = StringResources.Language.SuccessText; return result; } /// /// 发送数据异步返回的方法 /// /// 异步对象 private void SendCallBack( IAsyncResult ar ) { if (ar.AsyncState is StateObject state) { try { Socket socket = state.WorkSocket; int byteSend = socket.EndSend( ar ); state.AlreadyDealLength += byteSend; if (state.AlreadyDealLength < state.DataLength) { // 继续发送数据 socket.BeginSend( state.Buffer, state.AlreadyDealLength, state.DataLength - state.AlreadyDealLength, SocketFlags.None, new AsyncCallback( SendCallBack ), state ); } else { // 发送完成 state.WaitDone.Set( ); } } catch (Exception ex) { // 发生了异常 state.IsError = true; LOG.Write(ex, "SendCallback"); state.ErrerMsg = ex.Message; state.WaitDone.Set( ); } } } #if !NET35 /// /// 发送一个异步的数据信息,该方式在NET35里是不可用的。 /// /// 网络的套接字 /// 数据内容 /// 是否发送成功 protected OperateResult SendAsync( Socket socket, byte[] data ) { if (data == null) return OperateResult.CreateSuccessResult( ); if (data.Length == 0) return OperateResult.CreateSuccessResult( ); var state = new StateObjectAsync( data.Length ); state.Tcs = new TaskCompletionSource( ); state.WorkSocket = socket; state.Buffer = data; try { socket.BeginSend( state.Buffer, state.AlreadyDealLength, state.DataLength - state.AlreadyDealLength, SocketFlags.None, new AsyncCallback( SendAsyncCallBack ), state ); bool boolResult = state.Tcs.Task.Result; return OperateResult.CreateSuccessResult( ); } catch (Exception ex) { return new OperateResult( ex.Message ); } } private void SendAsyncCallBack( IAsyncResult ar ) { if (ar.AsyncState is StateObjectAsync state) { try { Socket socket = state.WorkSocket; state.AlreadyDealLength += socket.EndSend( ar ); if (state.AlreadyDealLength < state.DataLength) { // 继续发送数据 socket.BeginSend( state.Buffer, state.AlreadyDealLength, state.DataLength - state.AlreadyDealLength, SocketFlags.None, new AsyncCallback( SendAsyncCallBack ), state ); } else { // 发送完成 state.Tcs.SetResult( true ); } } catch (Exception ex) { state.IsError = true; LOG.Write(ex, "SendAsyncCallBack"); state.Tcs.SetException( ex ); } } } #endif #endregion #region Socket Connect /// /// 创建一个新的socket对象并连接到远程的地址,默认超时时间为10秒钟 /// /// Ip地址 /// 端口号 /// 返回套接字的封装结果对象 /// /// /// protected OperateResult CreateSocketAndConnect( string ipAddress, int port ) { return CreateSocketAndConnect( new IPEndPoint( IPAddress.Parse( ipAddress ), port ), 10000 ); } /// /// 创建一个新的socket对象并连接到远程的地址 /// /// Ip地址 /// 端口号 /// 连接的超时时间 /// 返回套接字的封装结果对象 /// /// /// protected OperateResult CreateSocketAndConnect( string ipAddress, int port, int timeOut ) { return CreateSocketAndConnect( new IPEndPoint( IPAddress.Parse( ipAddress ), port ), timeOut ); } /// /// 创建一个新的socket对象并连接到远程的地址 /// /// 连接的目标终结点 /// 连接的超时时间 /// 返回套接字的封装结果对象 /// /// /// protected OperateResult CreateSocketAndConnect( IPEndPoint endPoint, int timeOut ) { if (UseSynchronousNet) { var socket = new Socket( AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.Tcp ); try { HslTimeOut connectTimeout = new HslTimeOut( ) { WorkSocket = socket, DelayTime = timeOut }; ThreadPool.QueueUserWorkItem( new WaitCallback( ThreadPoolCheckTimeOut ), connectTimeout ); socket.Connect( endPoint ); connectTimeout.IsSuccessful = true; return OperateResult.CreateSuccessResult( socket ); } catch (Exception ex) { socket?.Close( ); LOG.Write(ex, "CreateSocketAndConnect"); return new OperateResult( ex.Message ); } } else { OperateResult result = new OperateResult( ); ManualResetEvent connectDone = null; StateObject state = null; try { connectDone = new ManualResetEvent( false ); state = new StateObject( ); } catch (Exception ex) { return new OperateResult( ex.Message ); } var socket = new Socket( AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.Tcp ); // 超时验证的信息 HslTimeOut connectTimeout = new HslTimeOut( ) { WorkSocket = socket, DelayTime = timeOut }; ThreadPool.QueueUserWorkItem( new WaitCallback( ThreadPoolCheckTimeOut ), connectTimeout ); try { state.WaitDone = connectDone; state.WorkSocket = socket; socket.BeginConnect( endPoint, new AsyncCallback( ConnectCallBack ), state ); } catch (Exception ex) { // 直接失败 connectTimeout.IsSuccessful = true; // 退出线程池的超时检查 LOG.Write(ex, ToString()); // 记录错误日志 socket.Close( ); // 关闭网络信息 connectDone.Close( ); // 释放等待资源 result.Message = StringResources.Language.ConnectedFailed + ex.Message; // 传递错误消息 return result; } // 等待连接完成 connectDone.WaitOne( ); connectDone.Close( ); connectTimeout.IsSuccessful = true; if (state.IsError) { // 连接失败 result.Message = StringResources.Language.ConnectedFailed + state.ErrerMsg; socket?.Close( ); return result; } result.Content = socket; result.IsSuccess = true; state.Clear( ); state = null; return result; } } /// /// 当连接的结果返回 /// /// 异步对象 private void ConnectCallBack( IAsyncResult ar ) { if (ar.AsyncState is StateObject state) { try { Socket socket = state.WorkSocket; socket.EndConnect( ar ); state.WaitDone.Set( ); } catch (Exception ex) { // 发生了异常 state.IsError = true; LOG.Write(ex, "ConnectCallBack"); state.ErrerMsg = ex.Message; state.WaitDone.Set( ); } } } #if !NET35 private OperateResult ConnectAsync( IPEndPoint endPoint, int timeOut ) { var socket = new Socket( AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.Tcp ); var state = new StateObjectAsync( ); state.Tcs = new TaskCompletionSource( ); state.WorkSocket = socket; // timeout check HslTimeOut connectTimeout = new HslTimeOut( ) { WorkSocket = socket, DelayTime = timeOut }; ThreadPool.QueueUserWorkItem( new WaitCallback( ThreadPoolCheckTimeOut ), connectTimeout ); try { socket.BeginConnect( endPoint, new AsyncCallback( ConnectAsyncCallBack ), state ); socket = state.Tcs.Task.Result; return OperateResult.CreateSuccessResult( socket ); } catch (Exception ex) { return new OperateResult( ex.Message ); } } private void ConnectAsyncCallBack( IAsyncResult ar ) { if (ar.AsyncState is StateObjectAsync state) { try { Socket socket = state.WorkSocket; socket.EndConnect( ar ); state.Tcs.SetResult( socket ); } catch (Exception ex) { // 发生了异常 state.IsError = true; LOG.Write(ex, "ConnectAsyncCallBack"); state.ErrerMsg = ex.Message; state.Tcs.SetException( ex ); } } } #endif #endregion /***************************************************************************** * * 说明: * 下面的两个模块代码指示了如何读写文件 * ********************************************************************************/ #region Read Stream /// /// 读取流中的数据到缓存区 /// /// 数据流 /// 缓冲区 /// 带有成功标志的读取数据长度 protected OperateResult ReadStream( Stream stream, byte[] buffer ) { ManualResetEvent WaitDone = new ManualResetEvent( false ); FileStateObject stateObject = new FileStateObject { WaitDone = WaitDone, Stream = stream, DataLength = buffer.Length, Buffer = buffer }; try { stream.BeginRead( buffer, 0, stateObject.DataLength, new AsyncCallback( ReadStreamCallBack ), stateObject ); } catch (Exception ex) { LOG.Write(ex, ToString()); stateObject = null; WaitDone.Close( ); return new OperateResult( ); } WaitDone.WaitOne( ); WaitDone.Close( ); if (stateObject.IsError) { return new OperateResult( ) { Message = stateObject.ErrerMsg }; } else { return OperateResult.CreateSuccessResult( stateObject.AlreadyDealLength ); } } private void ReadStreamCallBack( IAsyncResult ar ) { if (ar.AsyncState is FileStateObject stateObject) { try { stateObject.AlreadyDealLength += stateObject.Stream.EndRead( ar ); stateObject.WaitDone.Set( ); } catch (Exception ex) { LOG.Write(ex, ToString()); stateObject.IsError = true; stateObject.ErrerMsg = ex.Message; stateObject.WaitDone.Set( ); } } } #endregion #region Write Stream /// /// 将缓冲区的数据写入到流里面去 /// /// 数据流 /// 缓冲区 /// 是否写入成功 protected OperateResult WriteStream( Stream stream, byte[] buffer ) { ManualResetEvent WaitDone = new ManualResetEvent( false ); FileStateObject stateObject = new FileStateObject { WaitDone = WaitDone, Stream = stream }; try { stream.BeginWrite( buffer, 0, buffer.Length, new AsyncCallback( WriteStreamCallBack ), stateObject ); } catch (Exception ex) { LOG.Write(ex, ToString()); stateObject = null; WaitDone.Close( ); return new OperateResult( ex.Message ); } WaitDone.WaitOne( ); WaitDone.Close( ); if (stateObject.IsError) { return new OperateResult( ) { Message = stateObject.ErrerMsg }; } else { return OperateResult.CreateSuccessResult( ); } } private void WriteStreamCallBack( IAsyncResult ar ) { if (ar.AsyncState is FileStateObject stateObject) { try { stateObject.Stream.EndWrite( ar ); } catch (Exception ex) { LOG.Write(ex, ToString()); stateObject.IsError = true; stateObject.ErrerMsg = ex.Message; } finally { stateObject.WaitDone.Set( ); } } } #endregion #region Object Override /// /// 返回表示当前对象的字符串 /// /// 字符串 public override string ToString( ) { return "NetworkBase"; } #endregion } }