/// <summary> /// Catches all exceptions thrown when action is executed and removes the master end point. /// The exception is ignored when it simply signals a master closing its connection. /// </summary> internal void CatchExceptionAndRemoveMasterEndPoint(Action action, string endPoint) { if (action == null) throw new ArgumentNullException("action"); if (endPoint == null) throw new ArgumentNullException("endPoint"); if (endPoint.IsNullOrEmpty()) throw new ArgumentException("Argument endPoint cannot be empty."); try { action.Invoke(); } catch (IOException ioe) { _log.DebugFormat("IOException encountered in ReadHeaderCompleted - {0}", ioe.Message); ModbusMasterTcpConnectionClosed.Raise(this, new TcpConnectionEventArgs(EndPoint)); SocketException socketException = ioe.InnerException as SocketException; if (socketException != null && socketException.ErrorCode == Modbus.ConnectionResetByPeer) { _log.Debug("Socket Exception ConnectionResetByPeer, Master closed connection."); return; } throw; } catch (Exception e) { _log.Error("Unexpected exception encountered", e); throw; } }
private async Task HandleRequestAsync() { while (true) { #if ModBusDebug Debug.WriteLine($"Begin reading header from Master at IP: {EndPoint}"); #endif int readBytes = await Stream.ReadAsync(_mbapHeader, 0, 6).ConfigureAwait(false); if (readBytes == 0) { #if ModBusDebug Debug.WriteLine($"0 bytes read, Master at {EndPoint} has closed Socket connection."); #endif ModbusMasterTcpConnectionClosed?.Invoke(this, new TcpConnectionEventArgs(EndPoint)); return; } ushort frameLength = (ushort)IPAddress.HostToNetworkOrder(BitConverter.ToInt16(_mbapHeader, 4)); #if ModBusDebug Debug.WriteLine($"Master at {EndPoint} sent header: \"{string.Join(", ", _mbapHeader)}\" with {frameLength} bytes in PDU"); #endif _messageFrame = new byte[frameLength]; readBytes = await Stream.ReadAsync(_messageFrame, 0, frameLength).ConfigureAwait(false); if (readBytes == 0) { #if ModBusDebug Debug.WriteLine($"0 bytes read, Master at {EndPoint} has closed Socket connection."); #endif ModbusMasterTcpConnectionClosed?.Invoke(this, new TcpConnectionEventArgs(EndPoint)); return; } #if ModBusDebug Debug.WriteLine($"Read frame from Master at {EndPoint} completed {readBytes} bytes"); #endif byte[] frame = _mbapHeader.Concat(_messageFrame).ToArray(); #if ModBusDebug Debug.WriteLine($"RX from Master at {EndPoint}: {string.Join(", ", frame)}"); #endif var request = ModbusMessageFactory.CreateModbusRequest(_messageFrame); request.TransactionId = (ushort)IPAddress.NetworkToHostOrder(BitConverter.ToInt16(frame, 0)); // perform action and build response IModbusMessage response = _slave.ApplyRequest(request); response.TransactionId = request.TransactionId; // write response byte[] responseFrame = Transport.BuildMessageFrame(response); #if ModBusDebug Debug.WriteLine($"TX to Master at {EndPoint}: {string.Join(", ", responseFrame)}"); #endif await Stream.WriteAsync(responseFrame, 0, responseFrame.Length).ConfigureAwait(false); } }
/// <summary> /// Catches all exceptions thrown when action is executed and removes the master end point. /// The exception is ignored when it simply signals a master closing its connection. /// </summary> internal void CatchExceptionAndRemoveMasterEndPoint(Action action, string endPoint) { try { if (action == null) { throw new ArgumentNullException("action"); } if (endPoint == null) { throw new ArgumentNullException("endPoint"); } if (endPoint.IsNullOrEmpty()) { throw new ArgumentException("Argument endPoint cannot be empty."); } try { action.Invoke(); } catch (IOException ioe) { _log.DebugFormat("IOException encountered in ReadHeaderCompleted - {0}", ioe.Message); ModbusMasterTcpConnectionClosed.Raise(this, new TcpConnectionEventArgs(EndPoint)); SocketException socketException = ioe.InnerException as SocketException; if (socketException != null && socketException.ErrorCode == Modbus.ConnectionResetByPeer) { _log.Debug("Socket Exception ConnectionResetByPeer, Master closed connection."); return; } Console.WriteLine("Caught some unknown exception but not throwing it: " + ioe.Message); throw; } catch (ArgumentException e) { //We don't have handle this but we don't want to crash if (e.Message.Contains("Unsupported function code")) { Console.WriteLine(e.Message); } } catch (Exception e) { _log.Error("Unexpected exception encountered", e); Console.WriteLine("Caught some unknown exception but not throwing it: " + e.Message); throw; } } catch (Exception err) { Console.WriteLine("Caught Some Exception not thowing " + err.Message); } }
internal void ReadHeaderCompleted(IAsyncResult ar) { Debug.WriteLine("Read header completed."); CatchExceptionAndRemoveMasterEndPoint(() => { // this is the normal way a master closes its connection if (Stream.EndRead(ar) == 0) { Debug.WriteLine("0 bytes read, Master has closed Socket connection."); ModbusMasterTcpConnectionClosed.Raise(this, new TcpConnectionEventArgs(EndPoint)); return; } Debug.WriteLine("MBAP header: {0}", string.Join(", ", _mbapHeader)); ushort frameLength = (ushort)IPAddress.HostToNetworkOrder(BitConverter.ToInt16(_mbapHeader, 4)); Debug.WriteLine("{0} bytes in PDU.", frameLength); _messageFrame = new byte[frameLength]; Stream.BeginRead(_messageFrame, 0, frameLength, ReadFrameCompleted, null); }, EndPoint); }
/// <summary> /// Catches all exceptions thrown when action is executed and removes the master end point. /// The exception is ignored when it simply signals a master closing its connection. /// </summary> internal void CatchExceptionAndRemoveMasterEndPoint(Action action, string endPoint) { if (action == null) { throw new ArgumentNullException("action"); } if (endPoint == null) { throw new ArgumentNullException("endPoint"); } if (endPoint == string.Empty) { throw new ArgumentException(Resources.EmptyEndPoint); } try { action.Invoke(); } catch (IOException ioe) { Debug.WriteLine("IOException encountered in ReadHeaderCompleted - {0}", ioe.Message); ModbusMasterTcpConnectionClosed.Raise(this, new TcpConnectionEventArgs(EndPoint)); SocketException socketException = ioe.InnerException as SocketException; if (socketException != null && socketException.ErrorCode == Modbus.ConnectionResetByPeer) { Debug.WriteLine("Socket Exception ConnectionResetByPeer, Master closed connection."); return; } throw; } catch (Exception e) { Debug.WriteLine("Unexpected exception encountered: [{0}] {1}", e.GetType().Name, e.Message); throw; } }
internal void ReadHeaderCompleted(IAsyncResult ar) { Log.Debug("XmlSettingsReadFile header completed."); CatchExceptionAndRemoveMasterEndPoint(() => { // this is the normal way a master closes its connection if (Stream.EndRead(ar) == 0) { Log.Debug("0 bytes read, Master has closed Socket connection."); ModbusMasterTcpConnectionClosed.Raise(this, new TcpConnectionEventArgs(EndPoint)); return; } Log.Debug($"MBAP header: {_mbapHeader.JoinByCommas()}"); ushort frameLength = (ushort)IPAddress.HostToNetworkOrder(BitConverter.ToInt16(_mbapHeader, 4)); Log.Debug($"{frameLength} bytes in PDU."); _messageFrame = new byte[frameLength]; Stream.BeginRead(_messageFrame, 0, frameLength, ReadFrameCompleted, null); }, EndPoint); }
private async Task HandleRequestAsync() { var serialTransport = (IModbusSerialTransport)Transport; while (true) { try { // read request and build message byte[] frame = serialTransport.ReadRequest(); //Create the request IModbusMessage request = _modbusFactory.CreateModbusRequest(frame); //Check the message if (serialTransport.CheckFrame && !serialTransport.ChecksumsMatch(request, frame)) { string msg = $"Checksums failed to match {string.Join(", ", request.MessageFrame)} != {string.Join(", ", frame)}."; //Logger.Warning(msg); throw new IOException(msg); } //Apply the request // TODO: почистить класс и предусмотреть броадкаст request.SlaveAddress ==0 IModbusMessage response = _slaveNetwork.GetSlave(request.SlaveAddress) .ApplyRequest(request); if (response == null) { serialTransport.IgnoreResponse(); } else { Transport.Write(response); } } catch (IOException /*ioe*/) { //Logger.Warning($"IO Exception encountered while listening for requests - {ioe.Message}"); serialTransport.DiscardInBuffer(); ModbusMasterTcpConnectionClosed?.Invoke(this, new TcpConnectionEventArgs(EndPoint)); } catch (TimeoutException /*te*/) { //Logger.Trace($"Timeout Exception encountered while listening for requests - {te.Message}"); serialTransport.DiscardInBuffer(); } catch (InvalidOperationException) { // when the underlying transport is disposed break; } catch (Exception /*ex*/) { //Logger.Error($"{GetType()}: {ex.Message}"); serialTransport.DiscardInBuffer(); } /* // OLD CODE * // //Logger.Debug($"Begin reading header from Master at IP: {EndPoint}"); * * int readBytes = await Stream.ReadAsync(_mbapHeader, 0, 6).ConfigureAwait(false); * if (readBytes == 0) * { * //Logger.Debug($"0 bytes read, Master at {EndPoint} has closed Socket connection."); * ModbusMasterTcpConnectionClosed?.Invoke(this, new TcpConnectionEventArgs(EndPoint)); * return; * } * * ushort frameLength = (ushort)IPAddress.HostToNetworkOrder(BitConverter.ToInt16(_mbapHeader, 4)); * //Logger.Debug($"Master at {EndPoint} sent header: \"{string.Join(", ", _mbapHeader)}\" with {frameLength} bytes in PDU"); * * _messageFrame = new byte[frameLength]; * readBytes = await Stream.ReadAsync(_messageFrame, 0, frameLength).ConfigureAwait(false); * if (readBytes == 0) * { * //Logger.Debug($"0 bytes read, Master at {EndPoint} has closed Socket connection."); * ModbusMasterTcpConnectionClosed?.Invoke(this, new TcpConnectionEventArgs(EndPoint)); * return; * } * * //Logger.Debug($"Read frame from Master at {EndPoint} completed {readBytes} bytes"); * byte[] frame = _mbapHeader.Concat(_messageFrame).ToArray(); * //Logger.Trace($"RX from Master at {EndPoint}: {string.Join(", ", frame)}"); * * var request = _modbusFactory.CreateModbusRequest(_messageFrame); * request.TransactionId = (ushort)IPAddress.NetworkToHostOrder(BitConverter.ToInt16(frame, 0)); * * IModbusSlave slave = _slaveNetwork.GetSlave(request.SlaveAddress); * * if (slave != null) * { * //TODO: Determine if this is appropriate * * // perform action and build response * IModbusMessage response = slave.ApplyRequest(request); * response.TransactionId = request.TransactionId; * * // write response * byte[] responseFrame = Transport.BuildMessageFrame(response); * //Logger.Information($"TX to Master at {EndPoint}: {string.Join(", ", responseFrame)}"); * await Stream.WriteAsync(responseFrame, 0, responseFrame.Length).ConfigureAwait(false); * } */ } }