Передача файлов по сети

Модераторы: Duncon, Naeel Maqsudov, Игорь Акопян, Хыиуду

Ответить
Shouldercannon
Сообщения: 74
Зарегистрирован: 08 июн 2008, 15:49

19 янв 2016, 17:19

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

Код: Выделить всё

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 количество переданных байт выводится только после получения файла

Код: Выделить всё

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 Кб)
Ответить