delphi linux memcached 服务器的 delphi memcached 客户端工作在 windows 32 不在 linux 中,我认为编码问题

delphi memcached client for linux memcached server working in windows 32 not in linux , encoding issue I think

我在 delphi 10.3.2 中创建了这个测试控制台应用程序。

我可以在 "ubuntu linux" 上使用它从​​ win32 应用更新内存缓存服务器 运行ning, 如果我编译此控制台应用程序并 运行 它在 linux 上它将无法工作。

我认为这是一个编码问题。

program ProjecttestLinuxMemCach;

{$APPTYPE CONSOLE}

{$R *.res}

uses
  System.SysUtils, system.json,system.netencoding,system.DateUtils,
  idtcpclient,idGlobal;

var
   tcp : TIdTCPClient;
   s   : String;

begin
  try
    tcp := TIdTCPClient.Create;
    try
      tcp.ConnectTimeout :=    1000;
      tcp.ReadTimeout    :=    3000;
      tcp.Host := '192.168.30.141';  // my local memcached server running on linux.
      tcp.Port := 11211;
      tcp.ReuseSocket := rsTrue;
      s:='set q 0 0 1'+sLineBreak+'b'+sLineBreak;
      tcp.Connect;
       tcp.Socket.Write(s);
       repeat
        s:=  tcp.Socket.ReadLn(sLineBreak);
       until (s = 'END')or (  s='' ) or (  s='STORED' );
       writeln(s)
    finally
      tcp.Free;
    end;

     readln;
  except
    on E: Exception do
      Writeln(E.ClassName, ': ', E.Message);
  end;
end.

我试图将 sLineBreak 更改为 #10 以解决 Linux 相同的问题。 当我在 linux 上 运行 时,我得到空白响应并且未设置值。

知道如何修复吗?

谢谢

RTL 的 sLineBreak 常数在 Windows 上是 CRLF (#13#10) 但在 [=35 上只有 LF (#10) =].

根据 Memcached protocol spec:

There are two kinds of data sent in the memcache protocol: text lines and unstructured data. Text lines are used for commands from clients and responses from servers. Unstructured data is sent when a client wants to store or retrieve data. The server will transmit back unstructured data in exactly the same way it received it, as a byte stream. The server doesn't care about byte order issues in unstructured data and isn't aware of them. There are no limitations on characters that may appear in unstructured data; however, the reader of such data (either a client or a server) will always know, from a preceding text line, the exact length of the data block being transmitted.

Text lines are always terminated by \r\n. Unstructured data is also terminated by \r\n, even though \r, \n or any other 8-bit characters may also appear inside the data. Therefore, when a client retrieves data from a server, it must use the length of the data block (which it will be provided with) to determine where the data block ends, and not the fact that \r\n follows the end of the data block, even though it does.

Indy 的 IOHandler 有一个 WriteLn() 方法,可以在所有平台上发送 IdGlobal.EOL 常量(又名 CRLF)。如果您没有明确指定自己的终止符,IOHandler.ReadLn() 默认情况下会在所有平台上处理 CRLFLF 终止符。

为了在所有平台上获得一致的体验,我建议您从 TCP 代码中删除对 sLineBreak 的所有使用,让 Indy 为您处理换行符,例如:

program ProjecttestLinuxMemCach;

{$APPTYPE CONSOLE}

{$R *.res}

uses
  System.SysUtils, System.JSON, System.NetEncoding, System.DateUtils,
  IdTCPClient, IdGlobal;

var
  tcp : TIdTCPClient;
  s   : String;
begin
  try
    tcp := TIdTCPClient.Create;
    try
      tcp.ConnectTimeout :=    1000;
      tcp.ReadTimeout    :=    3000;
      tcp.Host := '192.168.30.141';  // my local memcached server running on linux.
      tcp.Port := 11211;
      tcp.ReuseSocket := rsTrue;
      tcp.Connect;
      try
        tcp.Socket.WriteLn('set q 0 0 1');
        tcp.Socket.WriteLn('b');
        repeat
          s := tcp.Socket.ReadLn;
        until (s = 'END') or (s = '' {and not tcp.Socket.ReadLnTimedOut}) or (s = 'STORED');
        Writeln(s);
      finally
        tcp.Disconnect;
      end;
    finally
      tcp.Free;
    end;
  except
    on E: Exception do
      Writeln(E.ClassName, ': ', E.Message);
  end;
  Readln;
end.