Форум программистов «Весельчак У»
  *
Добро пожаловать, Гость. Пожалуйста, войдите или зарегистрируйтесь.
Вам не пришло письмо с кодом активации?

  • Рекомендуем проверить настройки временной зоны в вашем профиле (страница "Внешний вид форума", пункт "Часовой пояс:").
  • У нас больше нет рассылок. Если вам приходят письма от наших бывших рассылок mail.ru и subscribe.ru, то знайте, что это не мы рассылаем.
   Начало  
Наши сайты
Помощь Поиск Календарь Почта Войти Регистрация  
 
Страниц: [1]   Вниз
  Печать  
Автор Тема: Передача файлов по сети  (Прочитано 1297 раз)
0 Пользователей и 1 Гость смотрят эту тему.
Shouldercannon
Постоялец

ru
Offline Offline

« : 19-01-2016 14:28 » 

Доброго времени суток!
Сделал передачу файлов через Socket и столкнулся с проблемами.

Код: (Delphi)
unit frm_ReceivingFile;

procedure TFormReceivingFile.FormCreate(Sender: TObject);
begin
  ProcReceivingFile('Test', 'test.txt', ExtractFilePath(Application.ExeName) + 'Downloads'); //!//

  ClientSocket1.Open; // Открываем сокет
  BReceive := False; // Режим клиента - приём команд
end;

procedure TFormReceivingFile.ProcReceivingFile(Nick, sFile, sFolder: String);
begin
  LUser.Caption := Nick;
  LFile.Caption := ExtractFileName(sFile);
  ReceptionFolder := sFolder;
end;

procedure TFormReceivingFile.ClientSocket1Connect(Sender: TObject;
  Socket: TCustomWinSocket);
begin
  LStatus.Caption := 'Приём...';
end;

procedure TFormReceivingFile.ClientSocket1Disconnect(Sender: TObject;
  Socket: TCustomWinSocket);
begin
  LStatus.Caption := 'Нет соединения';
end;

procedure TFormReceivingFile.ClientSocket1Read(Sender: TObject;
  Socket: TCustomWinSocket);
var
  s: AnsiString; // Принятый текст
begin
  s := Socket.ReceiveText;
  // Если клиент в режиме приёма файла, то...
  if BReceive then Writing(s) // Записываем данные в буфер
  else // Если клиент не в режиме приёма файла, то...
  if Copy(s, 1, Pos('<||>', String(s)) - 1) = '10' then // Если это команда принятия файла "10", то...
  begin
    MS := TMemoryStream.Create; // Создаём буфер для файла
    // Определяем имя файла
    Delete(s, 1, Pos('<||>', String(s)) + 3);
    sName := String(Copy(s, 1, Pos('<||>', String(s)) - 1));
    // Определяем размер файла
    Delete(s, 1, Pos('<||>', String(s)) + 3);
    Size := StrToInt(String(Copy(s, 1, Pos('<||>', String(s)) - 1))); // Определяем размер файла
    Delete(s, 1, Pos('<||>', String(s)) + 3); // Удаляем последний разделитель
    BReceive := True; // Переводим сервер в режим приёма файла
    Writing(s); // Записываем данные в буфер
  end;
end;

procedure TFormReceivingFile.Writing(s: AnsiString);
begin
  // Если принято байт меньше размера файла, то...
  if MS.Size < Size then MS.Write(s[1], Length(s)); // Записываем в буфер
  // Выводим прогресс закачки файла
  ProgressBar1.Position := MS.Size * 100 div Size;
  LReceived.Caption := Format('%s / %s', [GetNormalSize(MS.Size), GetNormalSize(Size)]);
  // Если файл принят, то...
  if MS.Size = Size then
  begin
    BReceive := False; // Переводим клиента в нормальный режим
    MS.Position := 0; // Переводим каретку в начало буфера
    MS.SaveToFile(Format('%s\%s', [ReceptionFolder, ExtractFileName(sName)])); // Сохраняем файл
    ClientSocket1.Socket.SendText('11'); // Посылаем команду "11", то есть файл принят
    FreeAndNil(MS); // Убиваем буфер
    LStatus.Caption := 'Файл принят';
  end;
end;
ProgressBar работает нормально, а в LStatus количество переданных байт выводится только после получения файла

Код: (Delphi)
unit frm_FileTransfer;

procedure TFormFileTransfer.FormCreate(Sender: TObject);
begin
  ServerSocket1.Open; // Открываем сокет
end;

procedure TFormFileTransfer.FormDestroy(Sender: TObject);
begin
  ServerSocket1.Close; // Закрываем сокет
end;

procedure TFormFileTransfer.ProcFileTransfer(Nick, sFile: String);
var
  Size: Integer;
  P: ^Byte;
begin
  LUser.Caption := Nick;
  LFile.Caption := ExtractFileName(sFile);

  Self.Show;

  MS := TMemoryStream.Create; // Создаём буфер для файла
  MS.LoadFromFile(sFile); // Загружаем файл в буфер
  ServerSocket1.Socket.Connections[0].SendText(AnsiString('10<||>' + sFile + '<||>' + IntToStr(MS.Size) + '<||>')); // Посылаем информацию о файле (файл и размер)
  MS.Position := 0; // Переводим каретку в начало файла
  P := MS.Memory; // Загружаем в переменную "P" файл
  Size := ServerSocket1.Socket.Connections[0].SendBuf(P^, MS.Size); // Посылаем файл
  // Выводим прогресс
  ProgressBar1.Position := Size * 100 div MS.Size;
  LReceived.Caption := Format('%s / %s', [GetNormalSize(Size), GetNormalSize(MS.Size)]);
end;

procedure TFormFileTransfer.ServerSocket1ClientConnect(Sender: TObject;
  Socket: TCustomWinSocket);
begin
  LStatus.Caption := 'Передача...';
end;

procedure TFormFileTransfer.ServerSocket1ClientDisconnect(Sender: TObject;
  Socket: TCustomWinSocket);
begin
  LStatus.Caption := 'Нет соединения';
end;

procedure TFormFileTransfer.ServerSocket1ClientRead(Sender: TObject;
  Socket: TCustomWinSocket);
begin
  // Если клиент принял файл, то...
  if Socket.ReceiveText = '11' then
  begin
    LStatus.Caption := 'Файл отправлен';
    FreeAndNil(MS); // Убиваем буфер
  end;
end;
PrograssBar стоит на месте, а в LStatus количество переданных байт сразу на максимуме (10 Кб / 10 Кб)
Записан
Finch
Спокойный
Администратор

il
Offline Offline
Пол: Мужской
Пролетал мимо


« Ответ #1 : 20-01-2016 17:48 » 

Delphi уже давно не занимался. Поэтому только обшие вопросы
1) Сокет синхронный или асинхронный.
2) В одном потоке происходит чтение?
3) Не думаю, что отрисовка Прогресс бара происходит мнгновенно, сразу после того, как ты поменял его значение.
4) не увидел, как ты настроил сокет на чтение. Но 10 килобайт при современных скоростях, это не о чем. Буквально доли секунды для передачи.
Записан

Не будите спашяго дракона.
             Джаффар (Коша)
Страниц: [1]   Вверх
  Печать  
 

Powered by SMF 1.1.21 | SMF © 2015, Simple Machines