Версия для печати темы
Нажмите сюда для просмотра этой темы в оригинальном формате
Форум программистов > Delphi: Сети > как передать файл


Автор: BSOD 15.2.2006, 23:10
поиском не нашел...
как передать файл (поток) при помощи idUDPClient и Server ???

Автор: _hunter 16.2.2006, 11:28
http://forum.vingrad.ru/index.php?showtopic=2359
там есть пример UDP чата. файл передавать не намного сложнее.

Автор: BSOD 16.2.2006, 15:52
тоесть файл передавать как текст?
(текст-то я умею =))

Автор: _hunter 16.2.2006, 15:56
должен и в бинарном виде уйти...

Автор: BSOD 16.2.2006, 16:03
всмысле smile
просто, допустим у serverSocket и ClientSocket есть такая штука, как socket.sendstream.. что довольно удобно, так вот я и спрашиваю, нет ли в индейцах чего таково?

Автор: Snowy 16.2.2006, 16:39
Там есть SendBuf. Работает по аналогии, только не со стримом, а с блоком данных.

Автор: BSOD 17.2.2006, 18:46
Вобщем, небольшая проблемка....
хочу передать скрин.
с одной стороны по таймеру делаю:
Код

  bitblt(bmp.canvas.Handle,0,0,screen.Width,screen.Height,dc,0,0,srccopy);
  jpg.Assign(bmp);
  jpg.CompressionQuality:=50;
  jpg.Compress;
  jpg.SaveToStream(str);
  str.Seek(0,soFromBeginning);
  idUDPClient2.Active:=true;
  idUDPClient2.Send('beg '+inttostr(str.Size));
  while str.Position<str.Size do
    begin
      str.Read(bb,sizeof(bb));
      idUDPClient1.SendBuffer(bb,sizeof(bb));
    end;
  idUDPClient2.Send('end');
  idUDPClient2.Active:=false;


с другой стороны:

у одного сервера onUDPread:
Код

  adata.Read(bb,sizeof(bb));
  str.Write(bb,sizeof(bb));


у другово:
Код

  SFS:=TStringStream.Create('');
  SFS.CopyFrom(adata,adata.Size);
  s:=SFS.DataString;
  if s='end' then
    begin
      if started then
        begin
          if str.Size=CRC then
            begin
              jp.loadFromStream(str);
              bmp:=Tbitmap.Create;
              bmp.Width:=screen.Width;
              bmp.Height:=screen.Height;
              jp.DIBNeeded;
              bmp.Assign(jp);
              bitblt(image1.Canvas.Handle,0,0,screen.Width,screen.Height,bmp.Canvas.Handle,0,0,srcCopy);
            end;
        end;
      str.Clear;
      started:=false;
    end;
  if pos('beg',s)<>0 then
    begin
      delete(s,1,4);
      CRC:=strtoint(s);
      str.Clear;
      started:=true;
    end;
  SFS.Free;


тоесть, сначала посылаю "beg", с другой стороны очищаю поток.
потом - по одному байту шлю весь поток
потом - шлю "end" и пытаюсь из принятого потока сделать JPG

так вот поток этот доходит уже совсем не таким, каким он был в начале, и при попытке перегнать его в jpg=>bmp - вылазит еррор, что типа jp - на самом деле не рисунок....

хотя, один раз он все-таки передался.....

что я делаю не так и что мне делать?

Автор: Snowy 17.2.2006, 19:00
UDP нельзя слать по одному байту. Это неконтролируемый протокол. Байти могут придти в совершенно произвольном порядке.
Шли блоками по 60кб.

Автор: BSOD 17.2.2006, 21:23
а по подробнее, как сие реализовать?

Автор: Snowy 17.2.2006, 21:52
Все также. Только отправляй не однобайтовый буфер, а используй буфер, большим размером.
Тут просто есть ограничение - ты не можешь за один раз отправить более 64 килобайт. А реально даже меньше. 60 вполне подойдет.
Но отправлять по 1 байту нельзя - UDP не сохраняет порядок в отличии от TCP.
Или используй TCP, или отправляй большими кусками - пока будешь отправлять новый кусок, старый уже дойдет.
Принцип отправки все тот же. Отличие лишь в том, что ты должен переписать часть данных в созданный буфер, отправить,переписать следующую часть и т.д.
В принципе то же самое, только используешь не 1байтовую переменную, а массив байтов.

Автор: Демо 18.2.2006, 00:26
Цитата(Snowy @ 17.2.2006, 21:52 Найти цитируемый пост)
пока будешь отправлять новый кусок, старый уже дойдет.


Думаю, что правильнее будет подход с идентификацией(нумерацией) каждого пакета на передающей стороне и "склеиванием" в соответствующем порядке на принимающей стороне. При этом еще необходимо реализовывать обработку ситуации с непринятыми и искаженными пакетами.
В общем, это написание полноценного протокола обмена.

Автор: Snowy 18.2.2006, 00:36
Проще будет с TCP. UDP вещь сложная и имеет много ньюансов.
Но справиться с ней можно... сломав пару десятков граблей.

Автор: BSOD 18.2.2006, 12:39
вроде заработало, но как-то через раз... нужно будет еще не тока на себе потестить...

Автор: Snowy 18.2.2006, 13:51
Цитата(BSOD @ 18.2.2006, 12:39 Найти цитируемый пост)
вроде заработало, но как-то через раз...
Ну так UDP и не является надежным протоколом.
Если что-то в пути потерялось, то картинку уже не соберешь.
А оно может теряться, перемешиваться...
Особенно на линиях плохого качества.
Работает по принципу - кинул в сеть и забыл.
А хочешь надежности и гарантированной доставки - это уже TCP.

Автор: Демо 18.2.2006, 18:43
Непонятно, почему UDP.
UDP имеет смысл использовать для передачи от сервера клиентам, как мне кажется, причем только в том случае, если потеря части данных некритична. Например, потоковая широковещательная трансляция видео по локальной сети, когда потеря пары кадров совершенно некритична.
Если уж использовать передачу на сервер - прямойсмысл использовать все преимущества TCP.

Автор: BSOD 19.2.2006, 15:42
ну вобщем то, здесь как-раз таки потеря пары скринов и не критична =)

Powered by Invision Power Board (http://www.invisionboard.com)
© Invision Power Services (http://www.invisionpower.com)