VTTB
Members-
Content Count
3 -
Joined
-
Last visited
Everything posted by VTTB
-
Handle KeepAlive messages in a separate Thread (Indy TIdTCPClient)
VTTB posted a topic in Network, Cloud and Web
Good day, I'm supposed to communicate with a Server that receives XML messages and sends XML data back, occasionally (every 30 seconds when there were no other messages passed) the server sends a KeepAlive XML message without the client asking for it, but the client has to answer to the message. So I have a TReceiveThread class, derived from TThread, that gets passed the TIdTCPClient which was created in the main thread aswell as a TCriticalSection for synchronization, implemented .Execute to check once a second if a KeepAlive message arrived and sends an answer back to the server. .Execute (pseudo code): .Execute while not Terminated TThread.Sleep(1000) lock.enter try try recevied data (exception on timeout) if message type is keepalive send ack message except end finally lock.leave end So far so good. Now I want to send other messages, for example on a button click from the main thread (pseudo code): create xml message lock.enter try try send xml message read data (exception on timeout) parse data except report timeout error end finally lock.leave end This also works with every message I've implemented. However, when I'm not sending a message for 30 seconds so the server sends a KeepAlive message that gets handled and answered in the thread, the next message I'm trying to send from the main thread will throw a EIdReadTimeout (I can see the data sent in Wireshark, but not the data received). When I then send the same message again I'm getting an answer. I've extensively checked for synchronization errors and dead data in the send/receive buffers, that all seems to be fine. when I change the code above to: create xml message lock.enter try try try read data (exception on timeout) <------ except end send xml message read data (exception on timeout) parse data except report timeout error end finally lock.leave end as if the first read in the main thread somehow changes the context so the second read works as expected any advice? -
Handle KeepAlive messages in a separate Thread (Indy TIdTCPClient)
VTTB replied to VTTB's topic in Network, Cloud and Web
I've implemented your suggestion, seems to work pretty good, thanks If I'm bored I might try to recreate the problem in a minimal example and post it here -
Handle KeepAlive messages in a separate Thread (Indy TIdTCPClient)
VTTB replied to VTTB's topic in Network, Cloud and Web
I realize that the proposed solution is probably better but I'm still trying to figure out what is happening here. I don't see a race between the threads here because they are mutually exclusive through a TCriticalSection, so the Receive Thread can never receive any other message than a KeepAlive because when a regular message is sent to the server the main thread holds the lock until the main thread has received the message, or a timeout occured (here lies the problem, the main thread is not receiving anything unless I read before I send and then read the answer) It also wouldnt be a problem the other way around. If the server would send a KeepAlive just when the Receive Thread has finished it's cycle and I'd then send a regular message from the main thread I should at least receive "garbage" in the main thread, but I receive nothing. Even if there'd be garbage that wouldnt be a problem, I'd just discard the KeepAlive and send the regular message because for the server that's also OK Between KeepAlive messages I have ~30 seconds to send and receive regular messages via the main thread without problems, even though the receive thread is checking for KeepAlive messages once a second and as soon as the receive thread has handled a KeepAlive message (received and answered, buffers are empty afterwards), the first regular message will fail, unless I read *before* I send. If there'd be something wrong with the bytes in the buffers I should at least receive garbage in the main thread, but I dont I will eventually redesign the thing but for now I'm curious why it's not working unless I read (and dont receive anything) in the main thread before sending and then reading again from the main thread.