Delphi 使用Indy将文件从服务器发送到客户端
我有两个程序,一个用于服务器,另一个用于客户端 服务器向客户端发送一个文件。在客户端中,我使用TIdTCPClient、tidthreadscomponent和tidtantizone组件 文件创建得很好,但线程永远不会结束。调试时,我从未免费使用Fs.Free 这是我的客户代码:Delphi 使用Indy将文件从服务器发送到客户端,delphi,tcpclient,indy10,Delphi,Tcpclient,Indy10,我有两个程序,一个用于服务器,另一个用于客户端 服务器向客户端发送一个文件。在客户端中,我使用TIdTCPClient、tidthreadscomponent和tidtantizone组件 文件创建得很好,但线程永远不会结束。调试时,我从未免费使用Fs.Free 这是我的客户代码: procedure TForm1.IdThreadComponentRun(Sender: TIdThreadComponent); var MsgDuServeur: string; Taille: Int
procedure TForm1.IdThreadComponentRun(Sender: TIdThreadComponent);
var
MsgDuServeur: string;
Taille: Integer;
Fs : TFileStream;
begin
MsgDuServeur:= Trim(IdTCPClient.IOHandler.ReadLn(nil));
MemoService.Lines.Add('Serveur : ' + MsgDuServeur);
if (MsgDuServeur = 'RECUP_ENCOURS') then
begin
try
Fs:= TFileStream.Create('C:\temp\client\1test.cds', fmCreate);
try
IdTCPClient.IOHandler.LargeStream:= True;
Taille:= IdTCPClient.IOHandler.ReadInt64();
IdTCPClient.IOHandler.ReadStream(Fs, -1, False);
IdThreadComponent1.Active:= False;
finally
Fs.Free;
end;
except
on E: Exception do
_MessageDlg(E.message, mtWarning, [mbOK], 0);
end;
end;
end;
这是我的服务器代码
procedure TServiceServeurTrf.IdTCPServerExecute(AContext: TIdContext);
var
Flux: TMemoryStream;
LStreamSize : int64;
begin
try
// Transfert de fichiers volumineux
Context.Connection.Socket.WriteLn('RECUP_ENCOURS');
AContext.Connection.IOHandler.LargeStream:= True;
Flux:= TMemoryStream.Create;
try
Flux.LoadFromFile(C:\Windows\Temp\Transfert\3000\1test.cds);
Flux.Position:= 0;
AContext.Connection.IOHandler.Write(Flux.Size);
AContext.Connection.IOHandler.Write(Flux, 0, True);
finally
FreeAndNil(Flux);
end;
except
EcrireLog('Erreur');
end;
end;
我删除了防冻液,在ReadStream之后,我使用IdThreadComponent1。Active:=False;现在没事了。
如何同步?事实上,我希望将progressbar与IdTCPClientWork、IdTCPClientWorkBegin、IdTCPClientWorkEnd一起使用,但我看不到它的进度,因为您误用了TIdIOHandler.WriteTStream和TIdIOHandler.ReadStream方法
在客户端,将ReadStream的AByteCount参数设置为-1,将AReadUntilDisconnect参数设置为False(默认值)会导致ReadStream在读取流数据之前为您读取流大小,其中,根据LargeStream属性,使用ReadInt32或ReadInt64读取流大小
最初,您的客户端调用ReadInt64并将结果保存为整数!然后调用ReadStream,将AByteCount设置为ReadInt64的结果,并将AReadUntilDisconnect设置为True。因此,无论实际发送了多少字节,ReadStream都将无限期地读取,直到服务器关闭连接
然后您将客户端代码更改为调用ReadStream,AByteCount设置为-1,AReadUntilDisconnect设置为False,但您事先没有删除对ReadInt64的调用,因此现在您有了对流大小的双重读取
在服务器端,将AWriteByteCount参数设置为True会导致WriteStream在发送流数据之前发送流大小,其中大小是使用WriteInt32或WriteInt64发送的,具体取决于LargeStream属性。但是,您的服务器代码在调用WriteStream之前正在调用WriteInt64,所以您有一个流大小的双重发送
访问UI时,您也没有与主线程同步
请尝试以下方法:
过程TForm1.IdThreadComponentRunSender:TIdThreadComponent;
变量
MsgDuServeur:字符串;
Fs:TFileStream;
开始
MsgDuServeur:=TrimIdTCPClient.IOHandler.ReadLn;
TThread.Synchronize
程序
开始
MemoService.Lines.Add'Serveur:'+MsgDuServeur;
终止
;
如果MsgDuServeur='RECUP_ENCOURS',则
开始
尝试
Fs:=TFileStream.Create'C:\temp\client\1test.cds',fmCreate;
尝试
IdTCPClient.IOHandler.LargeStream:=True;
IdTCPClient.IOHandler.ReadStreamFs,-1,False;//请将您的问题同时显示发送文件的服务器代码。但是,当您知道要发送的文件大小时,为什么要将ReadStream的AReadUntilDisconnect参数设置为True?它应该是假的。更好的方法是,如果将默认值设置为AByteCount=-1和AReadUntilDisconnect=False,那么ReadStream将为您处理ReadInt64。另外,仅供参考,对MemoService.Lines.Add和MessageDlg的调用需要与主UI线程同步,它们不能在工作线程中安全使用。如果你也在使用线程,为什么还要使用TID防冻剂呢?谢谢,我根据你的评论修改了我的源代码。我为你发布了一个答案。谢谢。我做了更改,但是当我删除IdThreadComponent1行时。Active:=False;在客户机中,第一次测试是可以的,但是当我关闭表单再次测试时,表单就不能了show@GB74这可能与停用线程无关。使用调试器确保您的客户端代码中其他地方没有我们看不到的问题。感谢您的帮助。下面是我的客户端代码我想使用progressbar,但我看不到progress@GB74那么您没有正确使用进度事件,但没有显示该代码。此外,事件是在读取/写入数据的同一线程中触发的,因此请确保在访问ProgressBar时同步对UI线程的访问。