我有一个在Delphi 10.3.2中创建的TEST控制台应用程序。
我可以通过win32应用程序更新在“ ubuntu linux”上运行的memcached服务器,如果我编译此控制台应用程序并在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.
对于Linux同样的问题,我试图将sLineBreak更改为#10。当我在linux上运行时,我得到空白响应,并且未设置值。
任何想法如何解决?
谢谢
RTL的sLineBreak
常数在Windows上为CRLF
(#13#10
),在Linux上仅为LF
(#10
)。
内存缓存协议中发送了两种数据:文本行和非结构化数据。文本行用于来自客户端的命令以及服务器的响应。客户端发送非结构化数据想要存储或检索数据。服务器将传回非结构化数据,其接收方式与字节完全相同流。服务器不在乎字节顺序问题非结构化数据,并且不了解它们。没有任何限制可能出现在非结构化数据中的字符;但是,读者这样的数据(客户端或服务器)将始终从前文本行,数据块的确切长度为传输。
文本行始终由\ r \ n]终止。非结构化数据为[[also即使\ r,\ n或任何其他8位字符也由\ r \ n终止可能还会出现在数据中。因此,当客户检索来自服务器的数据,它必须使用数据块的长度(将提供)以确定数据块的结束位置,而不是即使\ r \ n紧随数据块的末尾,做。
Indy的IOHandler
具有WriteLn()
方法,该方法在所有平台上发送IdGlobal.EOL
常数(又名CRLF
)。如果您未明确指定自己的终结器,则IOHandler.ReadLn()
会在所有平台上默认处理CRLF
和LF
终结器。
为了在所有平台上获得一致的体验,我建议您从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.