![]() |
| ||
|
|
Новости |
Поиск |
FAQ |
Статьи |
Книги |
Новости VCL
| | Форумы ЧАТ |
Орешник |
|
| |||
| |||
« предыдущая ветвь | форум | следующая ветвь »
не могу передать файл через TServerSocket [D7, XP]
KyRo © (2006-11-17 17:20:00)Мне нужно в не блокирующем режиме передать файл .
И у меня постоянно выскакивает ошибка от того что переодически приходит пустая строка,а когда ошибки нет то размер послаемых данных не совподает с размером полученых.
Как исправить такую сетуацию ?
Вот код сервера и то как я посылаю файл
var
ms:TMemoryStream;
begin
// Клиент получает команду на передачу файла.
if Socket.ReceiveText = 'ldimg' then
begin
ms:= TMemoryStream.Create;
try
// Получаем данные на передачу.
ms.LoadFromFile(ExtractFilePath(Application.ExeName)+'Img\'+Nomer+'.cab');
ms.Position:= 0;
// Добавляем длину данных, чтобы клиент знал,
// сколько данных будет передано
// Добавляем #0 , чтобы можно было определить,
// где заканчивается информация о размере.
Socket.SendText(IntToStr(ms.Size) + #0);
// Посылаем его.
Socket.SendStream(ms);
except
// Итак, осталось освободить поток, если что-то не так.
ms.Free;
end;
Serverimg.Active:=False;
Вот код клиента и то как я принимаю и сохраняю файл
s, sl: string;
begin
s:= Socket.ReceiveText;
// Если мы не в режиме приёма:
if Rec <> 5 then
begin
Rec := 5;
// Теперь нам необходимо получить длину потока данных.
SetLength(sl, StrLen(PChar(s))+1); // +1 for the null terminator
StrLCopy(@sl[1], PChar(s), Length(sl)-1);
DataSize:= StrToInt(sl);
Data:= TMemoryStream.Create;
// Удаляем информацию о размере из данных.
Delete(s, 1, Length(sl));
end;
// Сохраняем данные в файл, до тех пор, пока не получим все данные.
try
Data.write(s[1], length(s));
if Data.Size = DataSize then
begin
Data.Position:= 0;
Data.SaveToFile('c:\img.cab');
Data.Free;
Rec:= 6;
Socket.Close;
end;
except
Data.Free;
KyRo (2006-11-20 15:21:00) [1]ок буду пробовать
Сергей М. (2006-11-20 14:50:00) [2]Обработчик On[Client]Read;
var
Buf: array[0..4095] of Byte; //можно сделать лок.переменной
...
Len:= Socket.ReceiveBuf(Bга, SizeOf(Buf));
case Len of
-1: .... крит.ошибка транспорта
0: Socket.Close;// партнер закрыл соединение по своей инициативе
else
Data.WriteBuffer(Buf, Len); //получены очередные Len байт, запишем их в конец стрима (Data: T FileStream)
end;
....
end;
Джо (2006-11-20 14:06:00) [3]Куда "деваются" пакеты — это тебе, конечно, виднее. А вот так
finally
Data.SaveToFile('c:\1.cab');
лучше не делать.
KyRo (2006-11-20 12:59:00) [4]Вот сделал все просто без проверок и .т. д.
Размер буду отсылать когда даю команду клиенту конектится.
Len:= Socket.ReceiveLength;
GetMem(Bfr, Len);
// Если мы не в режиме приёма:
try
Socket.ReceiveBuf(Bfr^, Len);
Data.Write(Bfr^, Len);
Rec:=True;
finally
Data.SaveToFile('c:\1.cab');
FreeMem(Bfr);
end;
end;
Сохраняю в любом случае файл на диск .
Так вот иногда приходит 24 килобайт , а иногда 48 но до размера файла 90 кб не доходит куда то деваются пакеты !!
Куда они деваются ?
Сергей М. (2006-11-20 12:31:00) [5]
> предлогаете сохранять на диск что есть ?
Это единственное универсальное решение.
Причем для файлов значительного размера вполне может потребоваться организация прогресс-индикации приема-передачи, на стороне передатчика это реализуется простым наследованием TFileStream с перекрытием метода Write(), а вот на стороне приемника придется читать небольшими блоками равного размера, скажем, по 4 или 8 кбайт.
KyRo (2006-11-20 12:26:00) [6]
> Сергей М. © (20.11.06 11:55) [17]
>
> > он ведь принят не полностью.
>
>
> А если размер файла > 2 гб ?
То есть предлогаете сохранять на диск что есть ?
Сергей М. (2006-11-20 11:55:00) [7]
> он ведь принят не полностью.
А если размер файла > 2 гб ?
KyRo (2006-11-20 11:46:00) [8]
> > Чем вызвана такая срочная не обходимость
>
>
> Тем что твоя логика с Send/ReceiveText рано или поздно обречена
> на провал.
Ок Этим щас займусь
> if Data.Size = DataSize then ...
>
> А если не равно ?
А если не равно . Я не чего не делаю так как не могу сохранить файл он ведь принят не полностью.
Сергей М. (2006-11-20 11:34:00) [9]
> Чем вызвана такая срочная не обходимость
Тем что твоя логика с Send/ReceiveText рано или поздно обречена на провал.
> Ошибки тут ведь нет
И здесь ошибка, и далее по тексту.
Например,
if Data.Size =DataSize then ...
А если неравно ?
KyRo (2006-11-20 11:29:00) [10]
> Сергей М. © (20.11.06 11:22) [10]
>
> > Куда то теряются пакетов 5
>
>
> Ты их сам теряешь.
Может и сам !! Но не могу найти где !
KyRo (2006-11-20 11:28:00) [11]
> Сергей М. © (20.11.06 11:23) [12]
>
> > это да можно переделать
>
>
> Не можно, а нужно !
Чем вызвана такая срочная не обходимость. Ошибки тут ведь нет . Я его позже переделаю .
> Alexander Panov © (20.11.06 11:22) [9]
>
> > KyRo (20.11.06 11:19) [8]
>
>
> В секцию except попадаешь?
Нет ошибки не происходит ! Просто перестает происходить s:= Socket.ReceiveText; Из за этого количество даных что получил не совпадает с тем количеством которое должно быть и по этому файл не могу создать
Сергей М. (2006-11-20 11:23:00) [12]
> это да можно переделать
Не можно, а нужно!
KyRo (2006-11-20 11:23:00) [13]
> активно ищем ошибку в коде.
> она есть.
> но мне ее искать как-то недосуг. уж извините...
Ошибка из за чего происходила я нашол и убрал . Там по правде была в коде я писал пустой буфер в поток.<
Сергей М. (2006-11-20 11:22:00) [14]
> Куда то теряются пакетов 5
Ты их сам теряешь.
Alexander Panov (2006-11-20 11:22:00) [15]
> KyRo (20.11.06 11:19) [8]
В секцию except попадаешь?
KyRo (2006-11-20 11:19:00) [16]
> Зачем это делать в текстовом виде ?
>
> Посылай (см. SendBuf) для этой цели Int64-значение (ровно
> 8 байт, ни больше ни меньше) фактического размера передаваемого
> следом стрима.
>
> На принимающей стороне сначала читай это Int64-значение
> (см. ReceiveBuf) - оно укажет тебе полный размер передаваемого
> партнером стрима.
Ну это да можно переделать так скорее будет лучше ! Но даже в моем варианте я знаю сколько данных должно прийти , а они не приходят в полном объеме ! Куда то теряются пакетов 5 ть.(судя по их размерам) ?
Сергей М. (2006-11-20 11:14:00) [17]
> // Добавляем длину данных, чтобы клиент знал,
> // сколько данных будет передано
Зачем это делать в текстовомвиде ?
Посылай (см. SendBuf) для этой цели Int64-значение (ровно 8 байт, ни больше ни меньше) фактического размера передаваемого следом стрима.
На принимающей стороне сначала читай это Int64-значение (см. ReceiveBuf) - оно укажет тебе полный размер передаваемого партнером стрима.
KyRo (2006-11-20 11:12:00) [18]
> Dmitrij_K (17.11.06 19:13) [1]
> Отладчик тебе на что?
Отладчик на сервере показывает что все ок . Файд загрузился в поток и отправлен.
А отладчик на клиенте показывает что приходит 3 или 4 пакета каждый по 8 килобайт. Таким образом посылаю файл 90 кило байт , а приходит около 30 !! Куда девались остальные ?
medved_68 (2006-11-20 11:08:00) [19]
> А как же их склеить и как это все проконтролировать , что
> бы файл пришол в нормальном виде ?
KyRoделаешь считывание в буфер скажем размером 8192 байта. Считал, слил из буфера либо в поток либо на диск, и снова в цикле считываешь. И так до тех пор пока операция чтения буфера сокета не вернет количество считанных байт= 0. Это и есть условие выхода из цикла чтения. Ну а проверить размер данных можно, только если ты предусмотрел передачу этого размера с сервера. :)))
KyRo (2006-11-20 10:28:00) [20]
> Объясняю популярно" (С) Высоцкий
>
> У сокетов есть внутренний буфер. И он совершенно не обязан
> совпадать с размером твоего файла или размером передаваемых
> данных.
> Пакеты погут склеится а могут и не склеится. Может придни
> вместо одного пакета 10 мелкий.
> Учи мат часть по сокетам.
А как же их склеить и как это все проконтролировать , что бы файл пришол в нормальном виде ?