![]() |
|
|
|||||||
| Регистрация | << Правила форума >> | FAQ | Пользователи | Календарь | Поиск | Сообщения за сегодня | Все разделы прочитаны |
![]() |
|
|
Опции темы | Поиск в этой теме | Опции просмотра |
|
|
|
#1
|
|||
|
|||
|
Я к вам, господа, и вот по какому вопросу:
Возникла необходимость написания софтинки для передачи файлов в локальной сети. Помучав гугль и полистав соответствующую литературу, остановился на Indy 9 IdTcpServer и IdTcpClient. Сервер включен и слушает порт, клиент время от времени передает определенные файлы. Методом проб и ошибок сварганил более - менее рабочий вариант. В процессе тестирования обнаружился один неприятный подвох - большие файлы, размером в несколько сотен Мб передаваться категорически отказываются, на стороне сервера создается файл 0 байт. Короче говоря - пришел к выводу, что файл лучше передавать кусками, попробовал все это дело реализовать - ан нет, моих скромных познаний в этой области оказалось недостаточно. Перепробовал несколько вариантов - не то. Файл создается, что - то в него записывается, но размер в итоге отличается от оригинала. Как я это вижу: Клиент - файл загружается в FileStream, размер файла делится на размер блока(допустим 1000 байт) = получаем количество блоков. Отправляем на сервер количество блоков или размер файла. В цикле отправляем блоки, увеличивая с каждым проходом FileStream.Position на соответствующее значение. Сервер - создаем FileStream, опять же в цикле записываем полученые от клиента блоки в какой - то промежуточный буфер, копируем в FIleStream (например FS.CopyFrom(...)). По получению последнего блока или достижению FS определенного размера выходим из цикла. В общем буду весьма и весьма признателен за помощь в реализации всего этого безобразия. Ниже приведен код, который работает на данный момент и нуждается в доработке. З.Ы. Я не студент, в армию не отправляйте. Код:
...
Server: TIdTCPServer;
Client: TIdTCPClient;
...
procedure TForm1.Button1Click(Sender: TObject);
var
FileName : String;
FileSize : Cardinal;
p : Pointer;
begin
Client.Connect();
FileName := 'C:\1.rar';
with TFileStream.Create(FileName, fmOpenRead) do
try
FileName := ExtractFileName(FileName) + #00;
GetMem(p, 256);
try
CopyMemory(p, @FileName[1], Length(FileName));
Client.Socket.Send(p^, 256);
finally
FreeMem(p);
end;
FileSize := Size;
Client.Socket.Send(FileSize, SizeOf(FileSize));
GetMem(p, Size);
try
ReadBuffer(p^, Size);
Client.Socket.Send(p^, Size);
finally
FreeMem(p);
end;
finally
Free;
end;
Client.Disconnect;
end;
procedure TForm1.ServerExecute(AThread: TIdPeerThread);
var
FileName : PChar;
FileSize : Cardinal;
FS : TFileStream;
begin
GetMem(FileName, 256);
try
Athread.Connection.ReadBuffer(FileName^, 256);
Athread.Connection.ReadBuffer(FileSize, SizeOf(FileSize));
FS := TFileStream.Create(FileName, fmCreate);
try
aThread.Connection.ReadStream(FS, FileSize);
finally
FS.Free;
end;
finally
FreeMem(FileName);
end;
end;
procedure TForm1.FormCreate(Sender: TObject);
begin
Server.Active := true;
end;
procedure TForm1.FormClose(Sender: TObject; var Action: TCloseAction);
begin
Server.Active := false;
end; |
|
#2
|
|||
|
|||
|
1. Файл, особенно бинарник. лучше всего запаковать в Base64.
2. Дело в том, что очередность прихода пакетов тебе не гарантированна. Поэтому придется кусочки складывать как есть (нумеруя их) и по приходу последнего собирать файл целиком. 3. А зачем ты работаешь на таком низком уровне? Возьми TIdFTPClient/TIdFTPServer. Повесь с паролем на нестандартный порт. При желании еще SSL можно прикрутить. Гораздо будет проще. |
|
#3
|
|||
|
|||
|
Цитата:
Цитата:
Цитата:
Давненько как-то пытался написать фтп клиент сервер на них. Больно глючными показались. Да и помимо передачи файлов есть еще кое какие моменты, которые мне реализовать проще с IdTcpServer/Client |
|
#4
|
||||
|
||||
|
Делал на скорую руку передачу файлов через WinSock. Столкнулся с проблемой по поводу
Цитата:
1000 1000 1000 1000 На сервере можем получить такую картину: 1000 800 1000 600 600 т.е. уже 5 пакетов. Так что на пакеты опираться нельзя. Что еще придумать - пока не знаю. |
|
#5
|
|||
|
|||
|
Цитата:
Гораздо надежней считать размер файла - он передается на сервер (ReadBuffer(p^, Size); Client.Socket.Send(p^, Size) Но с реализацией всего этого механизма бьюсь еже третий день, все какая-то херня поручается![]() |