Search code examples
delphiunicodedelphi-xeindyindy10

Sending unicode command with TIdCmdTCPClient


I`m using Delphi XE6 and Indy 10

I want to send an Unicode String as Command to a TIdCMDTCPServer from a TIdCMDTCPClient

I`m sending command with SendCMD method of IdCMDTCPClient component but received command shown as ' ? ' Character !

In fact I have a Command (for example : "USER_REG") and some parameters with that and Parameters are an Unicode String ( Persian characters )

I have set encoding of command to IndyTextEncoding_UTF8 or Encode command with UTF8Encode function but there is no chance !

Example of Command :

CMD := 'USER_REG#register_user(' + QuotedStr('محمود مهری') + ')';
TCPClient.SendCmd(CMD, -1, IndyTextEncoding_UTF8);

or

TCPClient.SendCmd(UTF8Encode(CMD), -1, IndyTextEncoding_UTF8);

How can I send Unicode Strings as Command ?

thanks ...


Solution

  • TIdCmdTCPServer and TIdCmdTCPClient are not designed to be used together. If you are using TIdCmdTCPServer, you should be using TIdTCPClient instead. If you want to use TIdCmdTCPClient, then at the very least DO NOT use its SendCmd() or GetResponse() methods. TIdCmdTCPClient uses an internal reading thread to receive messages from the server. That thread will interfere with GetResponse()'s reading (SendCmd() calls GetResponse() internally). Use the client's IOHandler.WriteLn() method instead, and then let the TIdCmdTCPClient.CommandHandlers read the server's response.

    That being said, specifying IndyTextEncoding_UTF8 on the actual send is the correct thing to do. You can alternatively set the client's IOHandler.DefStringEncoding property instead. Either way, using UTF8Encode() in this situation is useless in Delphi 2009+, because SendCmd() (and WriteLn()) takes a UnicodeString as input, so the UTF-8 encoded RawByteString that UTF8Encode() returns will get converted by the RTL back to a UTF-16 UnicodeString, which IndyTextEncoding_UTF8 will then re-encode back to UTF-8 again during transmission. That is useless overhead.

    On the server side, you need to use IndyTextEncoding_UTF8 on the reads so the incoming UTF-8 encoded commands will be decoded correctly. Since TIdCmdTCPServer is doing the actual reading for you, you will have to assign IndyTextEncoding_UTF8 to the AContext.Connection.IOHandler.DefStringEncoding property in the OnConnect event. Otherwise, Indy's default encoding will be used instead, and that encoding is US-ASCII by default (configurable via the IdGlobal.GIdDefaultTextEncoding variable). That is why you are seeing the client's non-ASCII characters being converted to ? characters. US-ASCII does not supports characters above #127.