About Indy 10 TIdTCPServer and ramdom disconections - Printable Version +- Atozed Forums (https://www.atozed.com/forums) +-- Forum: Indy (https://www.atozed.com/forums/forum-8.html) +--- Forum: Indy General Discussion (https://www.atozed.com/forums/forum-9.html) +--- Thread: About Indy 10 TIdTCPServer and ramdom disconections (/thread-3666.html) |
About Indy 10 TIdTCPServer and ramdom disconections - PabloRomero - 11-29-2023 Dear Indy People. I have a serious problem and I can't find any information. I have a service made with Delphi and Indy 10. I made it with TIdTCPServer. It's a service that controls licenses with a "keep alive". Everything is based using the TIdTCPClient that runs the applications, exchanging information with the server service. They always exchange XML based structures, like text. In this XML, there is a "command" property. This property receives every 15 minutes the command "Keep" and the server answers "ok, here I am, Keep ok" and gives to the station that runs my application, status and login information. All the information is stored in memory in a structure based on Tlist<Types>. We know that there are threads that are executed in the TidTCPExecute event for each connection. In my services there are another parallel threads inside the service, to maintain it, renew licenses and clean up unused licenses. Everything accesses structures based on that Tlist<Lot of Types>. There are of course, other data sharewd by all those threads. Everything works ok. But... Here comes the problem. My application disconnects randomly, to some workstations. I suspect it must be because of the way I protect the structures and data shared by the threads. Going in detail We have the IdTCPServerExecute event Code: var The "TManejoPaquetesDOM.Procesa( xComando.Linea, Acontext, Server )" is a class like this Code: TManejoPaquetesDOM = class(TIdSync) The "DoSynchronize" does all the work with each connection receive from clients. Code: class procedure TManejoPaquetesDOM.Procesa(Linea: string; AContext: TIdContext; pServer: TidTCPServer ); As you can see, "TManejoPaquetesDOM = class(TIdSync)". This is who processes everything. As I understand it, TidSync makes all the other threads of IdTCPServerExecute threads wait for it to finish. I'm not sure if this is the best approach, ideally the process should be parallel without making anyone wait. All the structures when accessed by the other threads of my application are protected with a generic class I made like this Code: TControlBloqueos = class Each time the data shared by threads are accessed, those threads protect the data with an instance of this class, global to the whole service. This instance is created at the start of the service Code: Bloqueo := TControlBloqueos.Create; and all the threads accessing the data, proceed like this. Code: Bloqueo.lock; My problem is that I can't detect those random disconnections of some users from my system. My questions a) Is there a way to speed up what IdTCPServerExecute does? Not using TidSync? b) What is the best way to protect shared data between threads? I'm not sure what I did is the best approach. Regards Pablo Romero RE: About Indy 10 TIdTCPServer and ramdom disconections - rlebeau - 11-30-2023 (11-29-2023, 05:24 PM)PabloRomero Wrote: They always exchange XML based structures, like text. In this XML, there is a "command" property. This property receives every 15 minutes the command 15 minutes is a long time to keep a TCP connection sitting idle without any traffic. Some firewalls/routers will close an idle connection after just a few minutes. You might consider closing any TCP connection that is going to be sitting idle for awhile. Otherwise, assuming your "Keep" command is meant for keeping a license alive rather than keeping the TCP connection alive, you might consider sending a separate status/heartbeat command more frequently. Or even enabling TCP-level keep-alives on the connection itself. (11-29-2023, 05:24 PM)PabloRomero Wrote: All the information is stored in memory in a structure based on Tlist<Types>. Since you are worried about synchronization, why not use TThreadList<Types> instead? Or at least put a TCriticalSection around your TList (which is what TThreadList does)? (11-29-2023, 05:24 PM)PabloRomero Wrote: Here comes the problem. My application disconnects randomly, to some workstations. I suspect it must be because of the way I protect the structures and data shared by the threads. Possibly. TIdTCPServer does not disconnect clients randomly, however if a runtime Exception occurred while accessing your data, that could certainly kill your client threads. (11-29-2023, 05:24 PM)PabloRomero Wrote: As you can see, "TManejoPaquetesDOM = class(TIdSync)". This is who processes everything. As I understand it, TidSync makes all the other threads of IdTCPServerExecute threads wait for it to finish. Not exactly. It makes a request to the main UI thread to run the specified object method, blocking the calling thread until that request is finished. So, other calls to TThread.Synchronize()/TIdThread.Synchronize() (and TIdNotify.Notify()/TThread.Queue()) will synchronize with each other. Other threads that are not performing sync requests will be unaffected. (11-29-2023, 05:24 PM)PabloRomero Wrote: I'm not sure if this is the best approach, ideally the process should be parallel without making anyone wait. Then don't synchronize your processing. Only synchronize access to shared resources, like your TList, but do the actual processing outside of the syncs. (11-29-2023, 05:24 PM)PabloRomero Wrote: All the structures when accessed by the other threads of my application are protected with a generic class I made Then why are you synchronizing your processing if it is providing its own thread safety? (11-29-2023, 05:24 PM)PabloRomero Wrote: My problem is that I can't detect those random disconnections of some users from my system. Are you running your code inside the debugger when the disconnects occur? Are you logging errors (especially in the TIdTCPServer.OnException event)? (11-29-2023, 05:24 PM)PabloRomero Wrote: a) Is there a way to speed up what IdTCPServerExecute does? Not using TidSync? There is not enough context to answer that. We don't know what you are syncing and why, or what your processing is actually doing that might be getting bottlenecked. (11-29-2023, 05:24 PM)PabloRomero Wrote: b) What is the best way to protect shared data between threads? I'm not sure what I did is the best approach. Again, not enough context to answer that, since we can't see what you are trying to protect exactly. RE: About Indy 10 TIdTCPServer and ramdom disconections - PabloRomero - 12-02-2023 Wow, Remy, I have lots of questions, but I'll be brief. I think I was wrong about TidSync. I thought that a class(TidSync) runs itself, putting the rest of the connections on hold, until it finishes its job. In fact -correct me if I am wrong- TidTCPServer.OnExecute executes every connection, that the server receives. So this block of code. TidTCPServer.OnExecute Code: begin So, the line TMManagePackagesDOM.Process( xCommand.Line, Acontext, Server ) is executed for each connection that sends something to the server. I thought "TManagePackagesDOM.Process(..)", because it's TidSync, it executes and put everything that entered OnExecute on hold, until it's finished. That's why I synchronize it. So, A) whether I synchronize or not, Do I have to protect all the data structures accessed by all my threads and everything that is touched inside TMManagePackagesDOM.Process(..) ? I ask this because of what you say "Then don't synchronize your processing. Only synchronize access to shared resources, like your TList, but do the actual processing outside of the syncs." (...) and "Then why are you synchronizing your processing if it is providing its own thread safety?" B) I am interested in this "Keep Alive" topic. I use it to keep licenses alive. But this point you say "..Or even enabling TCP-level keep-alives on the connection itself." Do dou have some example about this? Regards, and thank you very much, my friend. Pablo Romero Cordoba - Argentina |