0

I'm trying to change the connection type from the string (ReadLn) to an array of byte (ReadByte) and so I have a problem with the timeout property of TIdTCPServer.

How can identify timeout event in ReadByte mode and handle it? In ReadLn Mode by adding this line "AContext.Connection.IOHandler.ReadLnTimedout" can determine Timeout event but in ReadByte mode can not do this. After timeout by checking "ReadLnTimedout"

The other problem is deadlocking my program when trying to deactivate TIdTCPServer by setting Active := false. My program is blocking at this line :

AContext.Connection.IOHandler.ReadBytes(byte_buffer,-1,false);

And I can not get control of my code.

Here is my sample code

getdata1:
    try
      AddTo_memo1('wait to receive packet');      
      AContext.Connection.IOHandler.ReadBytes(byte_buffer,-1,false);
      AddTo_memo1('receive packet');
    except
      on e : Exception do
      begin
        AddTo_memo1('receive packet exc');
        //do something...
        raise;
      end;
    end;
    if AContext.Connection.IOHandler.ReadLnTimedout then goto getdata1;
            AddTo_memo1('receive packet without time out');

And after executing in memo1 I have:

wait to receive packet

wait to receive packet

receive packet

receive packet without time out

  • I don't quite understand what you are asking about regarding the timeout. But the only way the `Active` property deadlocks is if you are doing something in your event handlers that blocks the client threads from terminating properly. Such as synchronizing with the main thread while it is blocked waiting for the server to deactivate. Or swallowing Indy exceptions so the server does not process them. Etc. – Remy Lebeau Jul 21 '19 at 07:24
  • Thanks to Remy Lebeau. I solved deadlocking by correct synchronization. How can identify timeout event in ReadByte mode? In ReadLn Mode by adding this line "AContext.Connection.IOHandler.ReadLnTimedout" can determine this event but in ReadByte mode can not do this. It returns false value after the timeout occurs. – R_D Safatco Jul 26 '19 at 21:32
  • "*ReadByte ... returns false value after the timeout occurs*" - no it doesn't, as it doesn't have a return value. It raises an `EIdReadTimeout` exception if a timeout occurs. Which you are already coded to handle, so just add an `EIdReadTimeout` case to your `except` block, eg: `try ... except on e: EIdReadTimeout do begin ... end; on e : Exception do begin ... raise; end; end;` Or, you can call `IOHandler.CheckForDataOnSource()` with a timeout before calling `ReadBytes()` without a timeout. `CheckForDataOnSource()` will return False on timeout, not raise an exception. – Remy Lebeau Jul 26 '19 at 22:08
  • add the `EIdExceptionCore` unit to your `uses` clause – Remy Lebeau Jul 27 '19 at 02:27
  • I have a sign in my code to check its execute follow.see my sample code again, I edit it again. But no exceptions are applied all the time and I'm sure the client does n't send any data. Anyway, I change my code and trying to do ... except on e: EIdReadTimeout do begin ... end; on e : Exception do begin ... raise; end; end;. but undeclared identifier error for EIdReadTimeout happen. – R_D Safatco Jul 27 '19 at 02:28
  • I already told you how to fix the "unidentified" error (add the `EIdExceptionCore` unit to your `uses` clause). And the log messages you show make perfect sense. Your code waits and gets a timeout you don't log, waits and gets a timeout you don't log, gets a packet you do log, and then you check `ReadLnTimedout` which is false because it does not apply to `ReadBytes` only to `ReadLn`. Get rid of that check, and add `EIdReadTimeout` to your `except`, and you will get the results you are expecting. – Remy Lebeau Jul 27 '19 at 18:44
  • Special Thanks to Remy Lebeau. Undeclared identifier error solved by adding IdExceptionCore unit to the uses clause. But no exceptions are applied all the time. After execute code and waiting for a packet to receive In memo1 I have Like this: wait to receive packet. wait to receive packet. receive packet. receive packet without time out. And it repeats equal to the time of timeout. Please Check the evet on My sample code. – R_D Safatco Jul 27 '19 at 22:27
  • if `EIdReadTimeout` is not being raised then you have only one option left - set the length of `byte_buffer` to 0 before calling `ReadBytes()`, and then if `ReadBytes()` exits without exception then check the new length of `byte_buffer` and if it is still 0 then a timeout must have occurred. And you still need to get rid of the `ReadLnTimedout` check, it is useless in this code – Remy Lebeau Jul 28 '19 at 04:48
  • Thanks to Remy Lebeau. I check the new length of byte_buffer and solve the problem. – R_D Safatco Aug 17 '19 at 06:55

0 Answers0