-
Notifications
You must be signed in to change notification settings - Fork 64
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Application stuck on poor network - Socket error 10054 #68
Comments
If the server unexpectedly closes the connection (without notifying the peer!), it will depend on the By default, it is |
Hi Jens
Thanks a lot for your answer.
*By default, it is 15_000 ms. You might want to lower that volume and make
sure your I/O is done in a background thread, not the main thread.*
==> Do you mean the object could be controllable only after 15000 ms in my
case?
==> There're 3 timeout parameters, which one is the right one
between ConnectTimeout, ReadTimeout, TimeOut?
==> Yes the TIdModbusBusClient object is embedded in a background thread
and not in the main.
Actually, when the socket error appears during readInput.., write...I don't
have a timeout period with TIdModbusBusClient object, I got immediately an
exception (sorry in french : Erreur de socket n 10054 Connexion
reinitialisee par l'homologue (peer)).
Once this kind of error appears, the object stays locked and no longer
controllable...I can not force it to disconnect, active=false, etc....It
seems the TCP port is not released and stays open...even after an amount of
time.
The actual workaround I found is to kill the object and sometimes it
doesn't work and I have to restart the application fully to retrieve the
TCP communication.
Best regards
Le mar. 19 nov. 2024 à 12:49, Jens Mertelmeyer ***@***.***> a
écrit :
… If the server unexpectedly closes the connection (without notifying the
peer!), it will depend on the Timeout property of the TIdModBusClient for
how long the ReadInputRegisters(..) will block.
By default, it is 15_000 ms. You might want to lower that volume and make
sure your I/O is done in a background thread, not the main thread.
—
Reply to this email directly, view it on GitHub
<#68 (comment)>,
or unsubscribe
<https://github.com/notifications/unsubscribe-auth/A4EXJCHBNSW5BP53PTRS6RL2BMQUNAVCNFSM6AAAAABRJKZMQCVHI2DSMVQWIX3LMV43OSLTON2WKQ3PNVWWK3TUHMZDIOBVGM4DQMJXGM>
.
You are receiving this because you authored the thread.Message ID:
***@***.***>
|
I honestly cannot reproduce your problem. If the server unexpectedly closes (or resets) the connection, then the But I cannot reproduce that something completely hangs up and never returns. I have used these components with hundreds of installations around the globe in heavy industrial lines, with external servers and clients from different manufacturers, as well as our own microchips. Consider the following Windows console application: uses
IdModbusServer,
IdModBusClient,
IdContext,
ModbusTypes;
type
TTest = class
class procedure HandleReadInputRegisters(
const Sender: TIdContext;
const RegNr, Count: Integer;
var Data: TModRegisterData;
const RequestBuffer: TModBusRequestBuffer;
var ErrorCode: Byte
);
class procedure TestConnectionResetByPeer();
end;
class procedure TTest.HandleReadInputRegisters(
const Sender: TIdContext;
const RegNr, Count: Integer;
var Data: TModRegisterData;
const RequestBuffer: TModBusRequestBuffer;
var ErrorCode: Byte
);
const
ERROR_ILLEGAL_ADDRESS = $02;
begin
// Just reset the connection
// Sender.Connection.Socket.Binding.Reset();
// just close the connection
//Sender.Connection.Disconnect();
// send back a peaceful error code
ErrorCode := ERROR_ILLEGAL_ADDRESS;
end;
procedure tryReadFrom(const client: TIdModBusClient);
const
REGISTER_NUMBER = 123;
var
registerValue: UInt16;
begin
try
if(client.ReadInputRegister(REGISTER_NUMBER, {out} registerValue)) then
WriteLn('registerValue: ', registerValue)
else
WriteLn('Nothing read back');
except
WriteLn('Reading the register failed');
end;
end;
class procedure TTest.TestConnectionResetByPeer();
var
server: TIdModBusServer;
client: TIdModBusClient;
begin
// set up a test server
server := TIdModbusServer.Create(nil);
server.OnReadInputRegisters := HandleReadInputRegisters;
server.Active := True;
// set up our client
client := TIdModbusClient.Create(nil);
client.Host := '127.0.0.1';
client.TimeOut := 1000 {ms}; // Feel free to play with this timeout value
tryReadFrom(client);
tryReadFrom(client);
WriteLn('We''re finished');
end;
begin
TTest.TestConnectionResetByPeer();
end.
Adjust the |
Also, have you considered using a network analyzing tool like Wireshark to see what exactly goes over the wire? |
Hi Jens
Unfortunately no, It's a good idea I can use this tool to trace what's
wrong.
Here's a part of my code
...
Try
....
Result := IdModBusClient.ReadCoils(iAdrr, ilng, RegDataCoils);
Except On E:Exception Do
Begin
IdModBusClient.Disconnect; <=== It's here I've the issue, as I
said, went 10053 socket error appears, no timeout is managed by the
IdModBusClient component but an exception (10053 Socket exception) is
raised and the background thread stuck here indefinitely
result := False;
End;
End;
...
I don't know, if the version of Delphi (Embarcadero® Delphi 11.0 Version
28.0.42600.6491) I use and the Indy components can also have an impact
of this strange behavior?
Which version of Delphi do you use?
Best regards
Le ven. 22 nov. 2024 à 16:59, Jens Mertelmeyer ***@***.***> a
écrit :
… Also, have you considered using a network analyzing tool like *Wireshark*
to see what exactly goes over the wire?
—
Reply to this email directly, view it on GitHub
<#68 (comment)>,
or unsubscribe
<https://github.com/notifications/unsubscribe-auth/A4EXJCDAQKRGAJEWTCXJI3L2B5IGXAVCNFSM6AAAAABRJKZMQCVHI2DSMVQWIX3LMV43OSLTON2WKQ3PNVWWK3TUHMZDIOJUGA4TGNZRGQ>
.
You are receiving this because you authored the thread.Message ID:
***@***.***>
|
Hi,I will try the below code on my Delphi version to see the behavior RegardsLe 22 nov. 2024 à 14:06, Jens Mertelmeyer ***@***.***> a écrit :
I honestly cannot reproduce your problem. If the server unexpectedly closes (or resets) the connection, then the TIdModbusClient will hang until the timeout is elapsed. This certainly cann be improved (I think).
But I cannot reproduce, that something completely hangs up and never returns.
Also, I have used this components with hundreds of installations around the globe in heavy industrial lines, with external servers and clients, as well as our own.
Consider the following Windows console application:
uses
IdModbusServer,
IdModBusClient,
IdContext,
ModbusTypes;
type
TTest = class
class procedure HandleReadInputRegisters(
const Sender: TIdContext;
const RegNr, Count: Integer;
var Data: TModRegisterData;
const RequestBuffer: TModBusRequestBuffer;
var ErrorCode: Byte
);
class procedure TestConnectionResetByPeer();
end;
class procedure TTest.HandleReadInputRegisters(
const Sender: TIdContext;
const RegNr, Count: Integer;
var Data: TModRegisterData;
const RequestBuffer: TModBusRequestBuffer;
var ErrorCode: Byte
);
const
ERROR_ILLEGAL_ADDRESS = $02;
begin
// Just reset the connection
// Sender.Connection.Socket.Binding.Reset();
// just close the connection
//Sender.Connection.Disconnect();
// send back a peaceful error code
ErrorCode := ERROR_ILLEGAL_ADDRESS;
end;
procedure tryReadFrom(const client: TIdModBusClient);
const
REGISTER_NUMBER = 123;
var
registerValue: UInt16;
begin
try
if(client.ReadInputRegister(REGISTER_NUMBER, {out} registerValue)) then
WriteLn('registerValue: ', registerValue)
else
WriteLn('Nothing read back');
except
WriteLn('Reading the register failed');
end;
end;
class procedure TTest.TestConnectionResetByPeer();
var
server: TIdModBusServer;
client: TIdModBusClient;
begin
// set up a test server
server := TIdModbusServer.Create(nil);
server.OnReadInputRegisters := HandleReadInputRegisters;
server.Active := True;
// set up our client
client := TIdModbusClient.Create(nil);
client.Host := '127.0.0.1';
client.TimeOut := 1000 {ms}; // Feel free to play with this timeout value
tryReadFrom(client);
tryReadFrom(client);
WriteLn('We''re finished');
end;
begin
TTest.TestConnectionResetByPeer();
end.
Adjust the HandleReadInputRegisters(..) as you see fit - You will see that the modbus client will always recover and the duration of how long it waits can be controlled with the Timeout property.
—Reply to this email directly, view it on GitHub, or unsubscribe.You are receiving this because you authored the thread.Message ID: ***@***.***>
|
Hi, I built a modbus test server to simulate the socket reset by peer error.
What I've done in my app to test, after an amount of false returned by readXXX/writeYYYY (after an socket error 10054, as connected flag is still in true value), I release (free up) the component, recreate it and perform a new connection to the modbus controller . But I noticed a strange and annoying behavior, I can destroy/recreate the component for 3 - 4 times with success (without any exception), perfom readXXX, writeYYYY with success until the next 10054 error where I free and recreate again and then the component lock the background thread on readXXX or writeYYYY functions. Is it possible to made a change when 10054 error appends to close / release properly the TCP port used by the component and update the connected flag to false? Best regards |
Hi
I experience some issues with the Modbus component. I noticed when the socket error 10054 append (The connection is reset by the peer application) during ReadInputRegisters, ReadCoil, etc... the component raise an exception and stuck.
Application can not be controlled anymore...
Regards
The text was updated successfully, but these errors were encountered: