![]() |
| ||
|
|
Новости |
Поиск |
FAQ |
Статьи |
Книги |
Новости VCL
| | Форумы ЧАТ |
Орешник |
|
| |||
| |||
« предыдущая ветвь | форум | следующая ветвь »
IdTCPClient1+IdTCPserver1 передача - получение файла [D7, XP]
Varkan © (2009-07-02 12:17:00)Необходимо с помощью программы сервера раздать файл по сети для программ клиентов. В сети может около 20-30 одновременных соединений. Использую для клиента такой кусочек кода:
try
vixid:=False;
repeat
IdTCPClient1.Connect(); //соединяюсь
try
RichEdit1.Lines.Add('Начал '+TimeToStr(now));
IdTCPClient1.WriteLn('Fail');
GetMem(FileName, 256);
try
IdTCPClient1.ReadBuffer(FileName^, 256);
IdTCPClient1.ReadBuffer(FileSize, SizeOf(FileSize));
FS := TFileStream.Create(ExtractFilePath(Application.ExeName)+FileName, fmCreate);
// тут создается файл в папке с программой
try
IdTCPClient1.ReadStream(FS, FileSize);//получаю файл
finally
FS.Free;
end;
finally
FreeMem(FileName);
end;
IdTCPClient1.WriteLn('otrimav');//шлю серверу что все вери гуд
IdTCPClient1.Disconnect;
vixid:=true;
RichEdit1.Lines.Add('Закончил '+TimeToStr(now));
except
IdTCPClient1.Disconnect;
RichEdit1.Lines.Add('Не передал '+TimeToStr(now));
end;
until vixid;
except
RichEdit1.Lines.Add('Не удалось присоиденится к серверу '+TimeToStr(now));
end;
Если файл небольшого размера(~20-30 Мб) то он нормально получается. Но если файл побольше будет то программа-клиент его не получает.
В сервере код передачи файла выглядит у меня так:s:=AThread.Connection.ReadLn();
if s='Fail' then
try
s:=AThread.Connection.Socket.Binding.PeerIP;
FileToSend := Edit1.Text; // тут файл, который мы рассылаем компу клиенту.
with TFileStream.Create(FileToSend, fmOpenRead) do
try
FileToSend := ExtractFileName(FileToSend) + #00;
GetMem(p, 256);
try
CopyMemory(p, @FileToSend[1], Length(FileToSend));
AThread.Connection.Socket.Send(p^, 256);
finally
FreeMem(p);
end;
FileSize := Size;
AThread.Connection.Socket.Send(FileSize, SizeOf(FileSize));
GetMem(p, Size);
try
ReadBuffer(p^, Size);
AThread.Connection.Socket.Send(p^, Size);
finally
FreeMem(p);
end;
finally
Free;
end;
s:=AThread.Connection.ReadLn();
except
// RichEdit1.Lines.Add('Не смог передать файл на '+s+' '+TimeToStr(now));
end;
AThread.Connection.Disconnect;
P.S. Помогите пожалуйста решить данную проблему. Надо сделать так чтоб б с 99,9% вероятностью файл передался на клиенты, когда сеть на 100% исправна.
Кстати подозреваю что нада исходный файл передавать по частях, а не весь сразу. Но как ето реализовать не могу понять.(но может я не прав)
Anatoly Podgoretsky (2009-07-03 08:56:00) [1]> Сергей М. (03.07.2009 08:32:13) [13]
С возможностью докачки и долбежки.
Varkan (2009-07-03 08:56:00) [2]
> готовым FTP-инструментарием - TIdFTP/TIdFTPServer ?
Нада тогда смотреть ети компоненты и разбиратся с ними. На даный момент меня удовлетворяет последнее решение. Причем ета программа будет передавать не только даные файла, но и текстовую информацию (string).
спс. Сергей М.
спс. Anatoly Podgoretsky
Можна закрывать обсуждение.
Сергей М. (2009-07-03 08:32:00) [3]
> Может тут где то есть какие то подводные камни?
Да не то чтобы подводные, но ..
АП ведь правильно намекнул: к чему этот самодельный велосипед, если фактически тоже самое делается готовымFTP-инструментарием - TIdFTP/TIdFTPServer ?
Varkan (2009-07-02 23:37:00) [4]Уважаемый Сергей М. большое Вам спасибоза помощь ...
Сейчас месяц-два у меня наверное не будет возможности протестить передачу файла по сети, но передача файла на одном компе происходит, и при етом мой вариант что написан выше, файлы даже на одном компе размером больше 80 мб. не передавал, а с Вашей помощью у меня получилося передать 500 мб. Надеюсь при использовании 20-30 компов еект будет тот же. Для начинающих и тех кто ищет как ето можно сделать напишу код передачи файла от сервера к клиету:
Клиент:
try
IdTCPClient1.Connect();
s:=IdTCPClient1.ReadLn();
file_name:=IdTCPClient1.ReadLn();
FS := TFileStream.Create(ExtractFilePath(Application.ExeName)+file_name, fmCreate);
try
try
IdTCPClient1.ReadStream(FS, StrToInt64(s));
finally
FS.Free;
end;
except
ShowMessage('Не получил');
end;
IdTCPClient1.Disconnect;
except
ShowMessage('Не соиденился');
end;
сервер:
procedure TForm1.IdTCPServer1Execute(AThread: TIdPeerThread);
begin
AThread.Connection.WriteLn(Label1.Caption);
AThread.Connection.WriteLn(ExtractFileName(Edit1.Text));
AThread.Connection.WriteFile(Edit1.Text);
AThread.Connection.Disconnect;
end;
Если че не так написал, скажите. Может тут где то есть какие то подводные камни?
P.S. Уважаемый Сергей М.с меня пивко при встрече :)))
Varkan (2009-07-02 22:37:00) [5]
> Да, вполне достаточно
Так, а почему в моем примере передачи-получения файла именно наIdTCPClient1.ReadStream(FS, FileSize);//получаю файл
происходит не получение файла, если он большого размера. Или здесь проблемы с
ReadBuffer(p^, Size);
AThread.Connection.Socket.Send(p^, Size);
Сергей М. (2009-07-02 21:54:00) [6]
> Или все же IdTCPClient1.ReadStream нада будет обходится?
Да, вполне достаточно, если передатчик непосредственно перед вызовом WriteFile выполнит передачу размера этого файла (Int64)
Varkan (2009-07-02 21:04:00) [7]Хорошо, допустим сервер посылает на запрос клиента размер файла и сам файл Connection.WriteFile. Тогда я непонимаю как обрабатывать на клиенте ету передачу. Почему нету IdTCPClient1.readlnFile? Или все же IdTCPClient1.ReadStream нада будет обходится?
Сергей М. (2009-07-02 20:16:00) [8]Не стОит, если кроме как файловыми операциями твои клиенты и твой сервер не озабочены
Varkan (2009-07-02 20:13:00) [9]
> Справка индейская - неважнецкая..
> Ныряй в исходники
Ну а ваще стоит заниматся IdTCPClient1+IdTCPserver1, или перейти и пробовать юзать IdFTP1 и IdFTPServer1 (никогда с ними не работал и даже не подозреваю как)?
Сергей М. (2009-07-02 19:57:00) [10]Справка индейская - неважнецкая..
Ныряй в исходники
Varkan (2009-07-02 17:32:00) [11]
> А где ты собссно ищешь эти методы - в справке или в исходниках
> ?
посмотрел в справке
Сергей М. (2009-07-02 14:53:00) [12]
> че то я не вижу у IOHandler всех тех методов
Я веду речь об Indy10, там они есть.
И тебе настоятельно рекомендую обновиться до 10-ки.
А где ты собссно ищешь эти методы - в справке или в исходниках ?
Varkan (2009-07-02 14:48:00) [13]Уважаемый Сергей М.че то я не вижу у IOHandler всех тех методов (Read/WriteLn, Connection.IOHandler.WriteFile). А не могли бы Вы показать часть кода передачи/приема файла. Есть Connection.WriteFile.
> но перед этим следует передать размер файла методом
Вообще ... зачнм передавать размер файла предварительно? Что бы сравнить в конце передачи и дать ответ передан он полностю или нет?
> По смыслу больше похоже на ФТП
То есть Вы предлагаете пробовать копать по созданию ФТП сервера?
Anatoly Podgoretsky (2009-07-02 12:54:00) [14]По смыслу больше похоже на ФТП
Сергей М. (2009-07-02 12:39:00) [15]К чему эти пляски с промежуточным буфером p ?
Для приема/передачи текстовой строки, содержащей имя файла, есть метод Connection.IOHandler.Read/WriteLn, а для приема/передачи стрима - Connection.IOHandler.Read/WriteStream
Можно и без стрима при передаче обойтись, благо есть метод Connection.IOHandler.WriteFile, но перед этим следует передать размер файла методом Connection.IOHandler.Write