Вы неправильно используете методы TIdIOHandler.Write(TStream)
и TIdIOHandler.ReadStream()
.
На стороне клиента задайте для параметра AByteCount
для ReadStream()
значение -1
и для параметра AReadUntilDisconnect
значение False
(которые являются значениями по умолчанию) заставляет ReadStream()
прочитать размер потока перед тем, как он прочитает данные потока, где размер читается с использованием ReadInt32()
или ReadInt64()
, в зависимости от свойства LargeStream
.
Изначально ваш клиент вызывал ReadInt64()
(и сохранял результат в Integer
!), А затем вызывал ReadStream()
с AByteCount
, для которого установлено ReadInt64()
и AReadUntilDisconnect
, установленным на True
. Таким образом, независимо от того, сколько байтов было отправлено, ReadStream()
будет считывать бесконечно, пока сервер не закроет соединение.
Затем вы изменили свой клиентский код на вызов ReadStream()
с AByteCount
, установленным на -1
и AReadUntilDisconnect
установлен на False
, но вы не удалили вызов на ReadInt64()
заранее, поэтому теперь у вас есть двойное чтение размера потока.
На стороне сервера, установка Параметр AWriteByteCount
в True
заставляет Write(TStream)
отправлять размер потока перед отправкой данных потока, где размер отправляется с использованием Write(Int32)
или Write(Int64)
, в зависимости от свойства LargeStream
. Но ваш серверный код вызывает Write(Int64)
перед вызовом Write(TStream)
, поэтому у вас есть двойная передача размера потока.
Вы также не синхронизируете с основным потоком при доступе к вашему пользовательскому интерфейсу.
Попробуйте вместо этого:
procedure TForm1.IdThreadComponentRun(Sender: TIdThreadComponent);
var
MsgDuServeur: string;
Fs : TFileStream;
begin
MsgDuServeur := Trim(IdTCPClient.IOHandler.ReadLn);
TThread.Synchronize(
procedure
begin
MemoService.Lines.Add('Serveur : ' + MsgDuServeur);
end
);
if (MsgDuServeur = 'RECUP_ENCOURS') then
begin
try
Fs := TFileStream.Create('C:\temp\client\1test.cds', fmCreate);
try
IdTCPClient.IOHandler.LargeStream := True;
IdTCPClient.IOHandler.ReadStream(Fs, -1, False); // <-- calls ReadInt64() internally for you!
finally
Fs.Free;
end;
except
on E: Exception do
IdTCPClient.Disconnect;
TThread.Queue(
procedure
begin
MessageDlg(E.message, mtWarning, [mbOK], 0);
end
);
end;
end;
end;
procedure TServiceServeurTrf.IdTCPServerExecute(AContext: TIdContext);
var
Flux: TMemoryStream;
begin
try
// Transfert de fichiers volumineux
Flux := TMemoryStream.Create; // <-- consider using TFileStream instead...
try
Flux.LoadFromFile(C:\Windows\Temp\Transfert\3000\1test.cds);
AContext.Connection.IOHandler.LargeStream := True;
AContext.Connection.IOHandler.WriteLn('RECUP_ENCOURS');
AContext.Connection.IOHandler.Write(Flux, 0, True); // <-- calls Write(Int64) internally for you!
finally
Flux.Free;
end;
except
EcrireLog('Erreur'); // <-- make sure this is thread-safe!
raise;
end;
end;