我尝试将数据库记录从服务器端应用程序传递到客户端应用程序。在客户端,我需要将我的数据存储到TStrings
集合中。
当我传递多行字段时,我在客户端收到两个单独的数据项,而不是一个多行数据项!我也尝试使用基于Unicode UTF8的命令,但不幸的是结果是一样的。
服务器端代码:
procedure TForm1.IdCmdTCPServer1CommandHandlers0Command(ASender: TIdCommand);
var
myData: TStrings;
begin
myData := TStringList.Create;
myData.Add('12'); // ID
myData.Add('This is a multi line' + #13#10 + 'description.'); // Descriptions
myData.Add('Thom Smith'); // Name
try
ASender.Context.Connection.Socket.Write(myData, True{, TIdTextEncoding.UTF8});
finally
myData.Free;
end;
end;
服务器端的 myData
调试时间值为:
myData[0] = '12'
myData[1] = 'This is a multi line'#$D#$A'description.'
myData[2] = 'Thom Smith'
客户端代码:
procedure TForm1.Button1Click(Sender: TObject);
var
myData: TStrings;
begin
with TIdTCPClient.Create(nil) do
begin
Port := 1717;
Host := 'localhost';
try
Connect;
//IOHandler.DefStringEncoding := TIdTextEncoding.UTF8;
myData := TStringList.Create;
try
SendCmd('greating');
Socket.ReadStrings(myData, -1{, TIdTextEncoding.UTF8});
eID.Text := myData[0]; // ID TEdit
mDes.Text := myData[1]; // Descriptions TMemo
eTelNo.Text := myData[2]; // Name TEdit
finally
myData.Free;
end;
finally
Disconnect;
Free;
end;
end;
end;
客户端的 myData
调试时间值:
myData [0] = '12' myData 1 ='这是一条多线' myData [2] ='description。'
Telnet结果:
实际上,应该保留myData[2]
的{{1}}已替换为“说明”字段的第二行! 'Thom Smith'
之后没有任何项目。 <{1}}不再可访问。
我认为这个问题与Indy的myData[2]
或myData[3]
程序有关,因为它将ItemCount发送为3,但是它发送了两个项目(一个正确,接下来是两个项目!)。
如何在不将Write
程序中断ReadStrings
分成两行的情况下将回车字符传递给另一方?
非常感谢。
答案 0 :(得分:2)
如果你想让TStrings.Text
忘记特殊字符 - 你应该在通过网络发送之前将它们转义,然后在之后取消转义。有很多方法可以逃脱,所以选择一个适合你的方式。
function EscapeString:(String): String --- your choice
function DeEscapeString:(String): String --- your choice
procedure SendEscapedStrings(const socket: TIdSocket; const data: TStrings);
var s: string; temp: TStringList;
begin
temp := TStringList.Create;
try
temp.Capacity := data.Count;
for s in data do
temp.Add( EscapeString( s ) );
socket.Write(temp);
finally
temp.Destroy;
end;
end;
procedure ReadDeescapedStrings(const socket: TIdSocket; const data: TStrings);
var s: string; temp: TStringList;
begin
temp := TStringList.Create;
try
Socket.ReadStrings(temp, -1);
data.Clear;
data.Capacity := temp.Count;
for s in temp do
temp.Add( DeEscapeString( s ) );
finally
temp.Destroy;
end;
end;
现在问题是您会为DeEscapeString
和EscapeString
选择什么?选项很多。
StrStringToEscaped
单位中选择非常简单的函数StrEscapedToString
和JclString
:什么样的逃避
如果您要求建议我建议不要使用原始TCP服务器。有着众所周知的标准HTTP协议,Delphi有很多库可以实现HTTP服务器和HTTP客户端。在协议(和库)中已经确定了诸如加密,压缩,语言支持等等。如果出现问题 - 你可以使用自己的HTTP嗅探器,看看谁在错误的地方或服务器上眼睛。调试要简单得多。
如果您刚刚开始,我建议您查看HTTP + JSON Synopse mORMot库,也许它可以满足您的需求。例如,您可以从http://robertocschneiders.wordpress.com/2012/11/22/datasnap-analysis-based-on-speed-stability-tests/或从lib中的演示中获取示例服务器代码。
然后,如果安排在原始TCP服务器周围,我会发送压缩数据,因此它会更好地工作(网络通常比CPU慢)。请参阅http://docwiki.embarcadero.com/CodeExamples/XE5/en/ZLibCompressDecompress_(Delphi)。
发送:
TStringStream
接收
TBytesStream
现在,如果你真的不想改变几乎任何东西,那么JCL逃避对你来说是足够的。至少它对我有用,但我的任务非常不同,根本不是网络。但是你可以测试它们,看看它是如何起作用的。
答案 1 :(得分:0)
不要使用TStrings
重载,因为它似乎使用换行符作为字符串之间的分隔符,如果您的字符串本身包含换行符,则不起作用。
您可以轻松编写自己的包装器方法,通过线路发送字符串列表(将其作为伪代码):
procedure WriteStrings(IOHandler : TIdIOHandler; Strings : TStrings);
var
Str : String;
begin
IOHandler.WriteBufferOpen;
try
IOHandler.Write(Strings.Count);
for Str in Strings do
IOHandler.Write(Str);
finally
IOHandler.WriteBufferClose;
end;
end;
procedure ReadStrings(IOHandler : TIdIOHandler; Strings : TStrings);
var
Count, I : Integer;
begin
Count := IOHandler.ReadInteger;
for I := 1 to Count do
Strings.Add(IOHandler.ReadString);
end;