Форум программистов
 

Восстановите пароль или Зарегистрируйтесь на форуме, о проблемах и с заказом рекламы пишите сюда - alarforum@yandex.ru, проверяйте папку спам!

Вернуться   Форум программистов > Delphi программирование > Общие вопросы Delphi
Регистрация

Восстановить пароль

Купить рекламу на форуме - 42 тыс руб за месяц

Ответ
 
Опции темы Поиск в этой теме
Старый 22.02.2016, 13:25   #1
Shouldercannon
Участник клуба Подтвердите свой е-майл
 
Аватар для Shouldercannon
 
Регистрация: 26.01.2008
Сообщений: 1,899
Вопрос Потеря данных при получениии файла

Так получаю файл
Код:
procedure TForm1.IdTCPClient1Connected(Sender: TObject);
var
  FS: TFileStream;
  FPath, FName: String;
begin
  FPath := ExtractFilePath(Application.ExeName) + 'Downloads';
  FName := IdTCPClient1.IOHandler.ReadLn;

  if not DirectoryExists(FPath) then ForceDirectories(FPath);

  FS := TFileStream.Create(FPath + '\' + ExtractFileName(FName), fmCreate); // Сохранение
  try
    CProgressBar.Max := IdTCPClient1.IOHandler.ReadLongInt(); // Из-за этой строки пропадает 4 байта
    IdTCPClient1.IOHandler.ReadStream(FS, -1, True); // Поток передаваемый сервером
  finally
    FreeAndNil(FS);
  end;

  IdTCPClient1.Disconnect;

  CLabel.Caption := 'Файл принят';
end;
Из-за
Код:
CProgressBar.Max := IdTCPClient1.IOHandler.ReadLongInt(); // Из-за этой строки пропадает 4 байта
пропадают 4 байта, если закомментировать этот участок, то всё нормально.
Пробовал
Код:
CProgressBar.Max := IdTCPClient1.IOHandler.ReadInt16(); - 42 байта вместо 44
CProgressBar.Max := IdTCPClient1.IOHandler.ReadInt32(); - 40 байта вместо 44
CProgressBar.Max := IdTCPClient1.IOHandler.ReadInt64(); - 36 байта вместо 44

CProgressBar.Max := IdTCPClient1.IOHandler.ReadUInt16(); - 42 байта вместо 44
CProgressBar.Max := IdTCPClient1.IOHandler.ReadUInt32(); - 40 байта вместо 44
CProgressBar.Max := IdTCPClient1.IOHandler.ReadUInt64(); - 36 байта вместо 44

CProgressBar.Max := IdTCPClient1.IOHandler.ReadByte; - 43 байта вместо 44
В чём загвостка?
Изображения
Тип файла: jpg Untitled-1.jpg (45.6 Кб, 138 просмотров)
Shouldercannon вне форума Ответить с цитированием
Старый 22.02.2016, 14:50   #2
Pavia
Лис
Старожил
 
Аватар для Pavia
 
Регистрация: 18.09.2015
Сообщений: 2,409
По умолчанию

Наконецто в ваших вопросах. Появились проблески сознания.
Без клиента ответить куда 4 байта(1 по картинке) пропали невозможно. Впредь приводите код клиента и сервера.

1) Инди это всего лишь корявая обёртка над сокетами. Как каша из тапора.
2) Вы бы чтонибудь почитали.

Ondisk =0 означает что файл либо ещё в кеше и не записан на диск. Либо, так как файл маленький, то он мог разместиться не в node а в журнале. Поэтому 0 нормально.

3)в Connected вставлять чтение неправильно.
Защиты от фрагментации пакетов у вас нету. Индейцы ленивые за вас этого несделали.
Хорошо поставленный вопрос это уже половина ответа. | Каков вопрос, таков ответ.
У дзен программиста программа делает то что он хотел, а не то что он написал .

Последний раз редактировалось Pavia; 22.02.2016 в 14:52.
Pavia вне форума Ответить с цитированием
Старый 22.02.2016, 15:03   #3
Alex11223
Старожил
 
Аватар для Alex11223
 
Регистрация: 12.01.2011
Сообщений: 19,500
По умолчанию

Так автор же вроде просто читает 4 байта сначала, а потом читает оставшиеся байты, почему-то думая что те 4 байта останутся там же.

А "что-нибудь почитать" ему во всех темах советуют, пока не помогло.
Ушел с форума, https://www.programmersforum.rocks, alex.pantec@gmail.com, https://github.com/AlexP11223
ЛС отключены Аларом.
Alex11223 вне форума Ответить с цитированием
Старый 22.02.2016, 15:13   #4
Shouldercannon
Участник клуба Подтвердите свой е-майл
 
Аватар для Shouldercannon
 
Регистрация: 26.01.2008
Сообщений: 1,899
По умолчанию

И большие и маленькие файлы рубятся из=за недостающих 4-х байт.
Цитата:
Сообщение от Alex11223 Посмотреть сообщение
Так автор же вроде просто читает 4 байта сначала, а потом читает оставшиеся байты, почему-то думая что те 4 байта останутся там же.

А "что-нибудь почитать" ему во всех темах советуют, пока не помогло.
"что-нибудь почитать" - понятие растяжимое. Тогда размер файла буду отсылать отдельно, коль так получается.
То что надо
Код:
...
const
  Host = '127.0.0.1';
  Port = 1120;
...
var
  Form1: TForm1;
  FName: String;

implementation

{$R *.dfm}

procedure TForm1.BSelectClick(Sender: TObject);
begin
  if OpenDialog1.Execute then
  begin
    FName := OpenDialog1.FileName;

    IdTCPServer1.DefaultPort := Port;
    IdTCPServer1.Active := True;
  end;
end;

procedure TForm1.BConnectClick(Sender: TObject);
begin
  IdTCPClient1.Host := Host;
  IdTCPClient1.Port := Port;
  IdTCPClient1.Connect;
end;

procedure TForm1.IdTCPClient1Connected(Sender: TObject);
var
  FS: TFileStream;
  FPath, FName: String;
  FSize: Integer;
begin
  FPath := ExtractFilePath(Application.ExeName) + 'Downloads';
  if not DirectoryExists(FPath) then ForceDirectories(FPath);

  FName := IdTCPClient1.IOHandler.ReadLn(); // Имя файла
  FSize := StrToIntDef(IdTCPClient1.IOHandler.ReadLn(), -1); // Размер файла

  CProgressBar.Max := FSize;

  FS := TFileStream.Create(FPath + '\' + ExtractFileName(FName), fmCreate); // Сохранение
  try
    IdTCPClient1.IOHandler.ReadStream(FS, -1, True); // Поток передаваемый сервером
  finally
    FreeAndNil(FS);
  end;

  IdTCPClient1.Disconnect;

  CLabel.Caption := 'Файл принят';
end;
...
////////////////////////////////////////////////////////////////////////////////
procedure TForm1.IdTCPServer1Connect(AContext: TIdContext);
var
  FS: TFileStream;
begin
  FS := TFileStream.Create(FName, fmOpenRead or fmShareDenyNone); // Загрузка
  try
    AContext.Connection.OnWork := Work;
    AContext.Connection.OnWorkBegin := WorkBegin;
    AContext.Connection.Socket.WriteLn(FName); // Имя файла
    AContext.Connection.Socket.WriteLn(IntToStr(FS.Size)); // Размер файла
    AContext.Connection.Socket.Write(FS); // Поток принимаемый клиентом
  finally
    FreeAndNil(FS);
  end;

  AContext.Connection.Disconnect;

  SLabel.Caption := 'Файл отправлен';
end;

procedure TForm1.IdTCPServer1Execute(AContext: TIdContext);
begin
  //!//
end;
...
end.

Последний раз редактировалось Shouldercannon; 22.02.2016 в 15:41.
Shouldercannon вне форума Ответить с цитированием
Старый 22.02.2016, 15:27   #5
Pavia
Лис
Старожил
 
Аватар для Pavia
 
Регистрация: 18.09.2015
Сообщений: 2,409
По умолчанию

Почитайте как правильно задавать вопросы.
https://rsdn.ru/Info/howtoask.xml
И вот это за одно:
www.gunsmoker.ru/2008/10/x-y-z.html?m=1

В самом инде есть пример простого ftp клиента и сервера. TIdTrivialFTPServer, TIdTrivialFTP. Для вас оно будет сложновато.
Но увы индейцы не ставили перед собой задачу упростить код.

Ошибки у вас от невнимательности рано вы за сеть взялись.
Вам бы на более простых задачках потренироваться. Там научитесь недопускать очевидных ошибок.

Правда это не спасёт от того что новичок не успев сказать раз 30 в уме ошибётся.
А для искоренения этого надо читать, прежде чем с наскоку браться за дело.

По сети советую почитать следующие книги:

Стивенс. UNIX. Разработка сетевых приложений
А. Оланд-Дж.-Программирование_в_сетях_Microsoft_ Windows-Питер(2002)

Indy in Depth, глубины Indy
Хорошо поставленный вопрос это уже половина ответа. | Каков вопрос, таков ответ.
У дзен программиста программа делает то что он хотел, а не то что он написал .

Последний раз редактировалось Pavia; 22.02.2016 в 16:09.
Pavia вне форума Ответить с цитированием
Старый 22.02.2016, 15:43   #6
Alex11223
Старожил
 
Аватар для Alex11223
 
Регистрация: 12.01.2011
Сообщений: 19,500
По умолчанию

Цитата:
Но увы индейцы не ставили перед собой задачу упростить код.
Как это не ставили? С сокетами без обертки сложнее работать же.
Ушел с форума, https://www.programmersforum.rocks, alex.pantec@gmail.com, https://github.com/AlexP11223
ЛС отключены Аларом.

Последний раз редактировалось Alex11223; 22.02.2016 в 16:16.
Alex11223 вне форума Ответить с цитированием
Старый 22.02.2016, 16:15   #7
Pavia
Лис
Старожил
 
Аватар для Pavia
 
Регистрация: 18.09.2015
Сообщений: 2,409
По умолчанию

Цитата:
Как это не ставили? С сокетами без обертки сложнее работать же.
Если бы ставили то сделали бы защиту от долгих пользовательских обработчиков. Нормально бы сделали потоки, а не оставляли на пользователя. Что нарушает все книги по архитектуре. Плюс обработку ошибок нормальную бы сделали. Не говоря уже про автоматы, которые у них попросту отсутствую.
Хорошо поставленный вопрос это уже половина ответа. | Каков вопрос, таков ответ.
У дзен программиста программа делает то что он хотел, а не то что он написал .
Pavia вне форума Ответить с цитированием
Старый 22.02.2016, 16:20   #8
Alex11223
Старожил
 
Аватар для Alex11223
 
Регистрация: 12.01.2011
Сообщений: 19,500
По умолчанию

Ну так ставить-то ставили (иначе зачем еще писать обертку?), а как получилось это уже другой вопрос.
Ушел с форума, https://www.programmersforum.rocks, alex.pantec@gmail.com, https://github.com/AlexP11223
ЛС отключены Аларом.
Alex11223 вне форума Ответить с цитированием
Ответ


Купить рекламу на форуме - 42 тыс руб за месяц



Похожие темы
Тема Автор Раздел Ответов Последнее сообщение
Потеря диаграммы при открытии файла Maxx Microsoft Office Excel 0 17.01.2012 16:45
Потеря части данных при отправке через TSocket Crystallon Работа с сетью в Delphi 7 02.10.2011 21:46
Потеря данных при записи в Named Pipe (именованный канал) zvukoper Win Api 0 27.02.2011 20:02
Потеря данных при изменении рамера раздела Drandulet Софт 5 06.07.2008 07:52