Форум: "Начинающим";
Текущий архив: 2006.12.10;
Скачать: [xml.tar.bz2];
Внизне могу передать файл через TServerSocket Найти похожие ветки
← →
KyRo (2006-11-17 17:20) [0]Мне нужно в не блокирующем режиме передать файл .
И у меня постоянно выскакивает ошибка от того что переодически приходит пустая строка,а когда ошибки нет то размер послаемых данных не совподает с размером полученых.
Как исправить такую сетуацию ?
Вот код сервера и то как я посылаю файл
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;
← →
Dmitrij_K (2006-11-17 19:13) [1]Отладчик тебе на что?
← →
oldman © (2006-11-17 19:15) [2]
> И у меня постоянно выскакивает ошибка от того что переодически
> приходит пустая строка,а когда ошибки нет то размер послаемых
> данных не совподает с размером полученых.
активно ищем ошибку в коде.
она есть.
но мне ее искать как-то недосуг. уж извините...
← →
MikePetrichenko © (2006-11-17 19:19) [3]"Объясняю популярно" (С) Высоцкий
У сокетов есть внутренний буфер. И он совершенно не обязан совпадать с размером твоего файла или размером передаваемых данных.
Пакеты погут склеится а могут и не склеится. Может придни вместо одного пакета 10 мелкий.
Учи мат часть по сокетам.
← →
KyRo (2006-11-20 10:28) [4]
> Объясняю популярно" (С) Высоцкий
>
> У сокетов есть внутренний буфер. И он совершенно не обязан
> совпадать с размером твоего файла или размером передаваемых
> данных.
> Пакеты погут склеится а могут и не склеится. Может придни
> вместо одного пакета 10 мелкий.
> Учи мат часть по сокетам.
А как же их склеить и как это все проконтролировать , что бы файл пришол в нормальном виде ?
← →
medved_68 © (2006-11-20 11:08) [5]
> А как же их склеить и как это все проконтролировать , что
> бы файл пришол в нормальном виде ?
KyRo делаешь считывание в буфер скажем размером 8192 байта. Считал, слил из буфера либо в поток либо на диск, и снова в цикле считываешь. И так до тех пор пока операция чтения буфера сокета не вернет количество считанных байт = 0. Это и есть условие выхода из цикла чтения. Ну а проверить размер данных можно, только если ты предусмотрел передачу этого размера с сервера. :)))
← →
KyRo (2006-11-20 11:12) [6]
> Dmitrij_K (17.11.06 19:13) [1]
> Отладчик тебе на что?
Отладчик на сервере показывает что все ок . Файд загрузился в поток и отправлен.
А отладчик на клиенте показывает что приходит 3 или 4 пакета каждый по 8 килобайт. Таким образом посылаю файл 90 кило байт , а приходит около 30 !! Куда девались остальные ?
← →
Сергей М. © (2006-11-20 11:14) [7]
> // Добавляем длину данных, чтобы клиент знал,
> // сколько данных будет передано
Зачем это делать в текстовом виде ?
Посылай (см. SendBuf) для этой цели Int64-значение (ровно 8 байт, ни больше ни меньше) фактического размера передаваемого следом стрима.
На принимающей стороне сначала читай это Int64-значение (см. ReceiveBuf) - оно укажет тебе полный размер передаваемого партнером стрима.
← →
KyRo (2006-11-20 11:19) [8]
> Зачем это делать в текстовом виде ?
>
> Посылай (см. SendBuf) для этой цели Int64-значение (ровно
> 8 байт, ни больше ни меньше) фактического размера передаваемого
> следом стрима.
>
> На принимающей стороне сначала читай это Int64-значение
> (см. ReceiveBuf) - оно укажет тебе полный размер передаваемого
> партнером стрима.
Ну это да можно переделать так скорее будет лучше ! Но даже в моем варианте я знаю сколько данных должно прийти , а они не приходят в полном объеме ! Куда то теряются пакетов 5 ть.(судя по их размерам) ?
← →
Alexander Panov © (2006-11-20 11:22) [9]
> KyRo (20.11.06 11:19) [8]
В секцию except попадаешь?
← →
Сергей М. © (2006-11-20 11:22) [10]
> Куда то теряются пакетов 5
Ты их сам теряешь.
← →
KyRo (2006-11-20 11:23) [11]
> активно ищем ошибку в коде.
> она есть.
> но мне ее искать как-то недосуг. уж извините...
Ошибка из за чего происходила я нашол и убрал . Там по правде была в коде я писал пустой буфер в поток.<
← →
Сергей М. © (2006-11-20 11:23) [12]
> это да можно переделать
Не можно, а нужно !
← →
KyRo (2006-11-20 11:28) [13]
> Сергей М. © (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; Из за этого количество даных что получил не совпадает с тем количеством которое должно быть и по этому файл не могу создать
← →
KyRo (2006-11-20 11:29) [14]
> Сергей М. © (20.11.06 11:22) [10]
>
> > Куда то теряются пакетов 5
>
>
> Ты их сам теряешь.
Может и сам !! Но не могу найти где !
← →
Сергей М. © (2006-11-20 11:34) [15]
> Чем вызвана такая срочная не обходимость
Тем что твоя логика с Send/ReceiveText рано или поздно обречена на провал.
> Ошибки тут ведь нет
И здесь ошибка, и далее по тексту.
Например,
if Data.Size = DataSize then ...
А если не равно ?
← →
KyRo (2006-11-20 11:46) [16]
> > Чем вызвана такая срочная не обходимость
>
>
> Тем что твоя логика с Send/ReceiveText рано или поздно обречена
> на провал.
Ок Этим щас займусь
> if Data.Size = DataSize then ...
>
> А если не равно ?
А если не равно . Я не чего не делаю так как не могу сохранить файл он ведь принят не полностью.
← →
Сергей М. © (2006-11-20 11:55) [17]
> он ведь принят не полностью.
А если размер файла > 2 гб ?
← →
KyRo (2006-11-20 12:26) [18]
> Сергей М. © (20.11.06 11:55) [17]
>
> > он ведь принят не полностью.
>
>
> А если размер файла > 2 гб ?
То есть предлогаете сохранять на диск что есть ?
← →
Сергей М. © (2006-11-20 12:31) [19]
> предлогаете сохранять на диск что есть ?
Это единственное универсальное решение.
Причем для файлов значительного размера вполне может потребоваться организация прогресс-индикации приема-передачи, на стороне передатчика это реализуется простым наследованием TFileStream с перекрытием метода Write(), а вот на стороне приемника придется читать небольшими блоками равного размера, скажем, по 4 или 8 кбайт.
← →
KyRo (2006-11-20 12:59) [20]Вот сделал все просто без проверок и .т. д.
Размер буду отсылать когда даю команду клиенту конектится.
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 14:06) [21]Куда "деваются" пакеты — это тебе, конечно, виднее. А вот так
finally
Data.SaveToFile("c:\1.cab");
лучше не делать.
← →
Сергей М. © (2006-11-20 14:50) [22]Обработчик 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: TFileStream)
end;
....
end;
← →
KyRo (2006-11-20 15:21) [23]ок буду пробовать
Страницы: 1 вся ветка
Форум: "Начинающим";
Текущий архив: 2006.12.10;
Скачать: [xml.tar.bz2];
Память: 0.51 MB
Время: 0.038 c