You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
I am experiencing problems with split packages received by ModbusMasterTcpConnection.
Some background: I have programmed a virtual Modbus device that wraps a real device with a proprietary communication protocol by using the ModbusTcpSlave.
I have a client that requests values from this virtual device once a second. At first it worked without any issues but after a while (several minutes) the communication breaks down with strange errors.
Closer examination with Wireshark and debugging the NModbus code shows that it receives an incomplete header package now and then because the TCP driver for whatever reason split the header package. This leads to all sorts of strange errors because the code does not wait for the rest of the header. To handle this I changed the NModbus code to use ReadAsync in a loop until all bytes have been read. This is my extension to the code in ModbusMasterTcpConnection:
private async Task HandleRequestAsync()
{
while (true)
{
Debug.WriteLine($"Begin reading header from Master at IP: {EndPoint}");
int readBytesTotal = 0;
while (readBytesTotal < 6)
{
int readBytes = await Stream.ReadAsync(_mbapHeader, readBytesTotal, 6 - readBytesTotal).ConfigureAwait(false);
if (readBytes == 0)
{
Debug.WriteLine($"0 bytes read, Master at {EndPoint} has closed Socket connection.");
ModbusMasterTcpConnectionClosed?.Invoke(this, new TcpConnectionEventArgs(EndPoint));
return;
}
readBytesTotal += readBytes;
}
ushort frameLength = (ushort)IPAddress.HostToNetworkOrder(BitConverter.ToInt16(_mbapHeader, 4));
Debug.WriteLine($"Master at {EndPoint} sent header: \"{string.Join(", ", _mbapHeader)}\" with {frameLength} bytes in PDU");
_messageFrame = new byte[frameLength];
readBytesTotal = 0;
while (readBytesTotal < frameLength)
{
int readBytes = await Stream.ReadAsync(_messageFrame, readBytesTotal, frameLength - readBytesTotal).ConfigureAwait(false);
if (readBytes == 0)
{
Debug.WriteLine($"0 bytes read, Master at {EndPoint} has closed Socket connection.");
ModbusMasterTcpConnectionClosed?.Invoke(this, new TcpConnectionEventArgs(EndPoint));
return;
}
readBytesTotal += readBytes;
}
Debug.WriteLine($"Read frame from Master at {EndPoint} completed {readBytesTotal} bytes");
byte[] frame = _mbapHeader.Concat(_messageFrame).ToArray();
Debug.WriteLine($"RX from Master at {EndPoint}: {string.Join(", ", frame)}");
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);
Debug.WriteLine($"TX to Master at {EndPoint}: {string.Join(", ", responseFrame)}");
await Stream.WriteAsync(responseFrame, 0, responseFrame.Length).ConfigureAwait(false);
}
}
I am experiencing problems with split packages received by ModbusMasterTcpConnection.
Some background: I have programmed a virtual Modbus device that wraps a real device with a proprietary communication protocol by using the ModbusTcpSlave.
I have a client that requests values from this virtual device once a second. At first it worked without any issues but after a while (several minutes) the communication breaks down with strange errors.
Closer examination with Wireshark and debugging the NModbus code shows that it receives an incomplete header package now and then because the TCP driver for whatever reason split the header package. This leads to all sorts of strange errors because the code does not wait for the rest of the header. To handle this I changed the NModbus code to use ReadAsync in a loop until all bytes have been read. This is my extension to the code in ModbusMasterTcpConnection: