delphiindyindy10tcpserver

Usage of LF on ReadLn in TIdTCPServer and WriteLn in TIdTCPClient


In my TIdTCPServer.OnConnect event, I receive information using:

AContext.Connection.IOHandler.ReadLn(LF, 5000)

I've read that ReadLn() expects LF on the end of strings, so do I need to add a LF at the end, like this?

TCPClient.IOHandler.WriteLn('TEXT' + LF);

I see in WriteLn() it already include that automatically:

procedure TIdIOHandler.WriteLn(const AOut: string;
  AByteEncoding: IIdTextEncoding = nil
  {$IFDEF STRING_IS_ANSI}; ASrcEncoding: IIdTextEncoding = nil{$ENDIF}
  );
begin
                                                                                  
  // which encodes a LF character to byte $25 instead of $0A (and decodes
  // byte $0A to character #$8E instead of #$A).  To account for that, don't
  // encoding the CRLF using the specified encoding anymore, force the encoding
  // to what it should be...
  //
  // But, what to do if the target encoding is UTF-16?
  {
  Write(AOut, AByteEncoding{$IFDEF STRING_IS_ANSI, ASrcEncoding{$ENDIF);
  Write(EOL, Indy8BitEncoding{$IFDEF STRING_IS_ANSI, Indy8BitEncoding{$ENDIF);
  }

  // Do as one write so it only makes one call to network
  Write(AOut + EOL, AByteEncoding
    {$IFDEF STRING_IS_ANSI}, ASrcEncoding{$ENDIF}
    );
end;

Solution

  • As you noted, IOHandler.WriteLn() automatically sends EOL (aka CRLF) at the end of each string. This is because most textual Internet protocols use CRLF.

    IOHandler.ReadLn() expects LF by default if you omit the terminator, but whenever the terminator is LF (implicitly or explicitly) then IOHandler.ReadLn() will also handle CRLF as well. So, DO NOT pass in your own LF to IOHandler.WriteLn(), eg:

    TCPClient.IOHandler.WriteLn('TEXT');
    

    If you want to send LF instead of CRLF, use IOHandler.Write() instead, eg:

    TCPClient.IOHandler.Write('TEXT' + LF);