#delphi #tcp #indy #delphi-10.3-rio
#delphi #tcp #indy #delphi-10.3-rio
Вопрос:
Я хочу отправить некоторые (большие) файлы через интернет-соединение с максимально возможной скоростью, используя Indy TCP. Я написал простое приложение, чтобы проверить, как работает соединение клиент-сервер Indy TCP.
Я обнаружил, что:
- все записи в сокет происходят мгновенно
- даже если
Disconnect
после записи данные все равно будут получены на другой стороне, если они будут прочитаны - данные могут иметь любой размер; я написал 100 МБ, и я получил каждый бит.
Таким образом, это означает, что в сокете есть буфер передачи, в который записывается. И похоже, что он может иметь любой размер… Если я записываю большой объем данных (скажем, 100 МБ), я думаю, что он передается не за одну операцию, а небольшими порциями (скажем, 1 МБ). Итак, по мере передачи данных этот буфер сжимается до тех пор, пока не достигнет нуля, когда все данные будут переданы. Что мне нужно, так это длина этого буфера в любое время, чтобы знать, когда его нужно заполнить, поэтому я могу писать непрерывно, не занимая всю память компьютера.
Я не знаю, имеет ли смысл то, что я написал здесь… Если нет, пожалуйста, скажите мне удалить вопрос и задать более общий вопрос. В итоге я хочу отправить файл через соединение Indy TCP с максимально возможной скоростью (имеется в виду асинхронный), но с индикатором выполнения и кнопкой отмены.
Это тестовое приложение:
procedure TClient.Execute;
var Cmd: Cardinal;
Txt: String;
Buff: TIdBytes;
Size: Integer;
begin
Size:= 5000000;
SetLength(Buff, Size);
Buff[0]:= 33;
Buff[Size-1]:= 55;
Client.Connect;
Cmd:= 1234;
Client.Socket.Write(Cmd);
Client.Socket.Write(Size);
Client.Socket.Write(Buff);
Txt:= 'client finished transmision';
SendMessage(RWnd, WM_USER, WPARAM(@Txt), 0);
Client.Disconnect;
Txt:= 'client disconected';
SendMessage(RWnd, WM_USER, WPARAM(@Txt), 0);
end;
procedure TForm1.ServerExecute(AContext: TIdContext);
var Cmd: Cardinal;
Mess: String;
Buff: TIdBytes;
Size: Integer;
begin
Mess:= 'Server ready';
SendMessage(Handle, WM_USER, WPARAM(@Mess), 0);
Cmd:= AContext.Connection.Socket.ReadUInt32;
Mess:= 'Server receive command';
SendMessage(Handle, WM_USER, WPARAM(@Mess), 0);
if Cmd = 1234 then begin
Size:= AContext.Connection.Socket.ReadInt32;
Sleep(4000);
Mess:= 'Server start reading';
SendMessage(Handle, WM_USER, WPARAM(@Mess), 0);
AContext.Connection.Socket.ReadBytes(Buff, Size);
Mess:= IntToStr(Buff[0]) ' / ' IntToStr(Buff[Size-1]);
SendMessage(Handle, WM_USER, WPARAM(@Mess), 0);
end;
Mess:= 'Server closed connection';
SendMessage(Handle, WM_USER, WPARAM(@Mess), 0);
end;
Комментарии:
1. это зависит от вашего протокола через tcp. отправьте полный размер файла в самом начале передачи или в качестве свойства заголовка
2. Я не думаю, что это зависит от моего протокола… Это больше похоже на внутренний механизм Indy … если это не что-то низкоуровневое… Я могу записать весь файл сразу в сокет подключения, но у меня не так много оперативной памяти (для этого внутреннего буфера). И я хочу установить максимальный объем для этого буфера, и когда данные считываются в другом размере и он опустошается, запишите в него больше данных, чтобы передача была непрерывной…
3. но вы также можете сделать то, что я написал
4. Буфер записи находится во внутренних элементах сокета в ядре ОС. У вас нет доступа, чтобы узнать, сколько данных находится в буфере записи в любой данный момент. Вы можете только знать, сколько данных вы просите поместить в буфер, и вы можете попросить ОС предварительно изменить размер буфера (но нет гарантии, что он выполнит этот запрос). Вам не нужно знать фактическое содержимое буфера, чтобы отобразить индикатор выполнения. Просто отобразите процент данных, которые вы запрашиваете для отправки.
5. @MarusNebunu вам не нужно обрабатывать это вручную. Просто отправьте как можно больше данных так быстро, как только сможете. TCP выполнит необходимое регулирование за вас. Если буфер записи заполнится, он заблокирует отправку дополнительных данных до тех пор, пока пространство не освободится. Если буфер очищается перед отправкой дополнительных данных, значит, вы отправляете недостаточно быстро в своем собственном коде.