![]() |
|
|
Регистрация | << Правила форума >> | 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
|
|||
|
|||
![]() Цитата:
Цитата:
Цитата:
![]() |
#4
|
||||
|
||||
![]() Делал на скорую руку передачу файлов через WinSock. Столкнулся с проблемой по поводу
Цитата:
1000 1000 1000 1000 На сервере можем получить такую картину: 1000 800 1000 600 600 т.е. уже 5 пакетов. Так что на пакеты опираться нельзя. Что еще придумать - пока не знаю. jmp $ ; Happy End! The Cake Is A Lie. |
#5
|
|||
|
|||
![]() Цитата:
![]() ![]() ![]() |