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

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

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

Восстановить пароль
Повторная активизация e-mail

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

Ответ
 
Опции темы Поиск в этой теме
Старый 25.11.2009, 23:23   #1
Cold_Night
Пользователь
 
Регистрация: 13.02.2009
Сообщений: 32
Печаль Ошибки передачи файлов (TServerSocket -> TClientSocket)

Всем привет. У меня неясная трабла с файлопередачей от сервера к клиенту на соответствующих компонентах. Собственно, вот код.

Код:
procedure TForm1.RbButton1Click(Sender: TObject); // отправка
begin
  T:=TFileStream.Create(LabeledEdit1.Text, fmOpenRead);  ServerSocket1.Socket.Connections[0].SendText('#'+LabeledEdit1.Text+'^'+IntToStr(T.Size));
  Sleep(400);
  ServerSocket1.Socket.Connections[0].SendStream(T);
end;

procedure TForm1.ServerSocket1ClientRead(Sender: TObject;
  Socket: TCustomWinSocket); //команда освободить буфер
begin
  if Socket.ReceiveText = 'DestroyBuffer' then T.Free;
end;
А вот код приёма
Код:
var TotalBytes: Int64 = 0;
    FSize: Cardinal = 0;
    FName: string = '';
    GetData: string = '';
    FS: TMemoryStream;
...

function GetSize(S: string): Int64; //функции парсинга имени файла, разм.
var I: Cardinal;
begin
  for I:=1 to Length(S) do
  if S[I] = '^' then
  begin
   Result:=StrToInt64(Copy(S, I + 1, Length(S)));
   Break;
  end;
end;

function GetName(S: string): string;
var I: Cardinal;
begin
  for I:=1 to Length(S) do
  if S[I] = '^' then
  begin
   Result:=Copy(S, 1, I - 1);
   Delete(Result, 1, 1);
   Result:=ExtractFileName(Result);
   Break;
  end;
end;

procedure TForm1.ClientSocket1Read(Sender: TObject;
  Socket: TCustomWinSocket); // приём файла
  var R: string;
  I: Cardinal;
begin
  R:=Socket.ReceiveText;
  if R[1] = '#' then
  begin
    FS:=TMemoryStream.Create;
    FSize:=GetSize(R);
    FName:=GetName(R);
  end
  else
  begin
  GetData:=GetData + R;
   TotalBytes:=TotalBytes + Length(R);
   if TotalBytes = FSize then
   begin
   // WriteFile(GetData, FName);
    for I:=1 to Length(GetData) do FS.WriteBuffer(GetData[I], 1);
    FS.SaveToFile(FName);
    FS.Free;
    ShowMessage('Received '+FName+': '+IntToStr(Length(GetData)));
    FName:='';
    TotalBytes:=0;
    GetData:='';
    ClientSocket1.Socket.SendText('DestroyBuffer');
   end;
  end;
end;
А теперь пара нюансов. Одни файлы принимает нормально, а когда отправляю другие - у клиента выскакивает мессаджбокс-ошибка с какой-то белибердой. И когда клиент отправляет команду освободить буфер, происходит какая-то ошибка. В чём может быть дело? Пожалуйста, для меня это очень важно.
Cold_Night вне форума Ответить с цитированием
Старый 26.11.2009, 14:18   #2
D_E_N
Форумчанин
 
Регистрация: 04.05.2009
Сообщений: 149
По умолчанию попробуй

Код:
//сервер
procedure TForm1.Button1Click(Sender: TObject); // Передаём файл
var
Size: integer;
P: ^Byte;
begin
MS := TMemoryStream.Create; // Создаём буфер для файла
MS.LoadFromFile(Edit1.Text); // Загружаем файл в буфер
// Посылаем информацию о файл (команда # название # размер)
ServerSocket1.Socket.Connections[0].SendText('file#'+Edit1.Text+'#'+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;
StatusBar1.SimpleText := 'Отправлено '+IntToStr(Size)+' из '+IntToStr(MS.Size)+' байт'
end;

procedure TForm1.ServerSocket1ClientRead(Sender: TObject;
Socket: TCustomWinSocket);
begin
if Socket.ReceiveText = 'end' then // Если клиент принял файл, то...
begin
StatusBar1.SimpleText := 'Клиент принял файл';
MS.Free; // Убиваем буфер
end;
end; 


//клиент
procedure Writing(Text: string); // Процедура записи в данных в буфер
private
{ Private declarations }
Name: string; // Имя файла
Size: integer; // Размер файла
Receive: boolean; // Режим клиента
MS: TMemoryStream; // Буфер для файла

procedure TForm1.Writing(Text: string);
begin
if MS.Size < Size then // Если принято байт меньше размера файла, то...
MS.Write(Text[1], Length(Text)); // Записываем в буфер
// Выводим прогресс закачки файла
ProgressBar1.Position := MS.Size*100 div Size;
StatusBar1.SimpleText := 'Принято '+IntToStr(MS.Size)+' из '+IntToStr(Size);
if MS.Size = Size then // Если файл принят, то...
begin
Receive := false; // Переводим клиента в нормальный режим
MS.Position := 0; // Переводим каретку в начало буфера
MS.SaveToFile(Name); // Сохраняем файл
ClientSocket1.Socket.SendText('end'); // Посылаем команду "end", то есть файл принят
MS.Free; // Убиваем буфер
StatusBar1.SimpleText := 'Файл принят';
end;
end; 

procedure TForm1.ClientSocket1Read(Sender: TObject;
Socket: TCustomWinSocket);
var
Rtext: string; // Принятый текст
begin
Rtext := Socket.ReceiveText;
if Receive then // Если клиент в режиме приёма файла, то...
Writing(RText) // Записываем данные в буфер
else // Если клиент не в режиме приёма файла, то...
if Copy(Rtext, 0, Pos('#', Rtext) -1) = 'file' then // Если это файл, то...
begin MS := TMemoryStream.Create; // Создаём буфер для файла
Delete(Rtext, 1, Pos('#', Rtext)); // Определяем имя файла
Name := Copy(Rtext, 0, Pos('#', Rtext) -1); // Определяем имя файла
Delete(Rtext, 1, Pos('#', Rtext)); // Определяем размер файла
Size := StrToInt(Copy(Rtext, 0, Pos('#', Rtext) -1)); // Определяем размер файла
Delete(Rtext, 1, Pos('#', Rtext)); // Удаляем последний разделитель
Label1.Caption := 'Размер файла: '+IntToStr(Size)+' байт'; // Выводим размер файла
Label2.Caption := 'Имя файла: '+Name; // Выводим имя файла
Receive := true; // Переводим сервер в режим приёма файла
Writing(RText); // Записываем данные в буфер
end;
end;
так проще мне кажется. и если немного подумать можно сделать с клиента передать файл серверу + небольшой чат
D_E_N вне форума Ответить с цитированием
Старый 26.11.2009, 17:43   #3
Cold_Night
Пользователь
 
Регистрация: 13.02.2009
Сообщений: 32
По умолчанию

Спасибо, разобрался
Cold_Night вне форума Ответить с цитированием
Ответ


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



Похожие темы
Тема Автор Раздел Ответов Последнее сообщение
Компоненты TServerSocket и TClientSocket Vadim Компоненты Delphi 5 15.03.2010 20:34
Tclientsocket и Tserversocket можно использовать в интернете? pro100-delphi Работа с сетью в Delphi 7 04.12.2009 19:11
TServerSocket, TClientSocket prod87 Работа с сетью в Delphi 7 26.10.2009 22:38
проблема с TServerSocket и с TClientSocket DOLBY Работа с сетью в Delphi 56 14.01.2008 16:12
Проблема с TClientSocket, TServerSocket PLOT_HD Работа с сетью в Delphi 4 11.08.2007 17:03