正如 Rufo 已经解释的那样,您没有正确地将数组写入和读取数组TMemoryStream
。
更糟糕的是,您也没有TMemoryStream
正确地通过套接字发送。和的默认参数TIdIOHandler.Write(TStream)
互TIdIOHandler.ReadStream()
不兼容。默认情况下,Write(TStream)
不发送TStream.Size
值。但是, 的默认参数ReadStream()
(与您显式传入的值相同)告诉它读取前几个字节并将它们解释为Size
,这在本示例中是非常错误的。
试试这个:
procedure TForm1.btnTestClick(Sender: TObject);
var
msRecInfo: TMemoryStream;
arrOf: Array of Integer;
i: Integer;
begin
SetLength(arrOf, 11);
for i := Low(arrOf) to High(arrOf) do
arrOf[i] := random(100);
msRecInfo := TMemoryStream.Create;
try
msRecInfo.WriteBuffer(arrOf[0], Length(arrOf) * SizeOf(Integer));
IdTCPClient1.IOHandler.Write(msRecInfo, 0, True);
finally
msRecInfo.Free;
end;
end;
procedure TForm1.IdTCPServer1Execute(AContext: TIdContext);
var
msRecInfo: TMemoryStream;
arrOf: Array of Integer;
i: Integer;
begin
msRecInfo := TMemoryStream.Create;
try
AContext.Connection.IOHandler.ReadStream(msRecInfo, -1, False);
SetLength(arrOf, msRecInfo.Size div SizeOf(Integer));
if Lenth(arrOf) > 0 then
begin
msRecInfo.Position := 0;
msRecInfo.ReadBuffer(arrOf[0], Length(arrOf) * SizeOf(Integer));
end;
finally
msRecInfo.Free;
end;
...
end;
或者,摆脱TMemoryStream
并自己发送单个Integer
值:
procedure TForm1.btnTestClick(Sender: TObject);
var
arrOf: Array of Integer;
i: Integer;
begin
SetLength(arrOf, 11);
for i := Low(arrOf) to High(arrOf) do
arrOf[i] := random(100);
IdTCPClient1.IOHandler.Write(Length(arrOf));
for I := Low(arrOf) to High(arrOf) do
IdTCPClient1.IOHandler.Write(arrOf[i]);
end;
procedure TForm1.IdTCPServer1Execute(AContext: TIdContext);
var
arrOf: Array of Integer;
i: Integer;
begin
i := AContext.Connection.IOHandler.ReadLongInt;
SetLength(arrOf, i);
for i := Low(arrOf) to High(arrOf) do
arrOf[i] := AContext.Connection.IOHandler.ReadLongInt;
...
end;
现在,话虽如此,TMemo
直接在OnExecute
事件处理程序中访问不是线程安全的。 TIdTCPServer
是一个多线程组件。该OnExecute
事件在工作线程的上下文中触发,而不是在主线程中触发。UI 组件,如TMemo
,不能从主线程外部安全地访问。您可以使用 Indy 的TIdNotify
或TIdSync
类与主线程同步,例如:
type
TMemoSync = class(TIdSync)
protected
FLine: String;
procedure DoSynchronize; override;
end;
procedure TMemoSync.DoSynchronize;
begin
Form1.Memo1.Lines.Add(FLine);
end;
procedure TForm1.IdTCPServer1Execute(AContext: TIdContext);
var
...
begin
...
with TMemoSync.Create do try
FLine := IntToStr(arrOf[1]);
Synchronize;
finally
Free;
end;
...
end;
如果不与主线程同步,可能会发生不好的事情。