BytesToRaw (Indy 10)
От: MikeSoft Украина msdn.at.ua
Дата: 22.06.10 19:32
Оценка:
Добрый день, уважаемые коллеги.

Реализовывая передачу изображения по протоколу UDP столкнулся с проблемой перевода TBytes в TMemoryStream.

Для теста создал новый проект. На форму поместил два TImage, один TButton, TIdUDPClient и TIdUDPServer.
В Image1 поместил PNG изображение (153 байта)

Настраиваю компоненты:
UDPServer->DefaultPort = 2050;
UDPClient->Port = 2050;
UDPClient->Host = "127.0.0.1";
UDPServer->Active = true;


В событии OnClick для Button1 выполняю передачу объекта серверу:
TMemoryStream *msS = new TMemoryStream();

TPngImage *png = new TPngImage();
png->Assign(Image1->Picture);

png->SaveToStream(msS);
msS->Position = soFromBeginning;

TByteDynArray DynArray = RawToBytes(msS,msS->Size);

delete png, msS;
png = NULL, msS = NULL;

UDPClient->SendBuffer(DynArray);


Передача проходит на "ура". Теперь обрабатываю событие OnUDPRead:
void __fastcall TForm1::UDPServerUDPRead(TIdUDPListenerThread *AThread, TBytes AData,
                    TIdSocketHandle *ABinding)
{
  TMemoryStream *msR = new TMemoryStream();
  TPngImage *png = new TPngImage();

  BytesToRaw(AData,msR,AData.Length);  // проблемое место
  msR->Position = soFromBeginning;
  png->LoadFromStream(msR);
  Image2->Picture->Graphic = png;

  delete png, msR;
  png = NULL, msR = NULL;
}


Картинка появляется в Image2, но при закрытии формы возникает Access Violation.

Функция BytesToRaw в третьем параметре требует int Size. Я передаю ей размер полученных данных (AData.Length) получаю всё тот же AV.
Пробую передать размер TBytes (пробовал также для TByteDynArray):
BytesToRaw(AData,msR,sizeof(AData));

В этом случае поток msR имеет нулевую длину и ссылается в NULL

Пробовал работать с этой функцией без сетевой передачи (далее изменённый код OnClick для Button1):
  TMemoryStream *msS = new TMemoryStream();

  TPngImage *png = new TPngImage();
  png->Assign(Image1->Picture);

  png->SaveToStream(msS);
  msS->Position = soFromBeginning;

  TByteDynArray DynArray = RawToBytes(msS,msS->Size);

  BytesToRaw(DynArray,msS,sizeof(DynArray));
  msS->Position = soFromBeginning;
  png->LoadFromStream(msS);
  mage2->Picture->Graphic = png;

  delete png, msS;
  png = NULL, msS = NULL;


Тогда ошибок не возникает.

Подскажите пожалуйста, что я делаю неправильно?
bytestoraw c++ builder 2010 indy 10 udp
Re: BytesToRaw (Indy 10)
От: icWasya  
Дата: 23.06.10 07:53
Оценка: 3 (1)
Здравствуйте, MikeSoft, Вы писали:

MS>Добрый день, уважаемые коллеги.


MS>Реализовывая передачу изображения по протоколу UDP столкнулся с проблемой перевода TBytes в TMemoryStream.


MS>Для теста создал новый проект. На форму поместил два TImage, один TButton, TIdUDPClient и TIdUDPServer.

MS>В Image1 поместил PNG изображение (153 байта)

MS>Настраиваю компоненты:

MS>
UDPServer->DefaultPort = 2050;
MS>UDPClient->Port = 2050;
MS>UDPClient->Host = "127.0.0.1";
MS>UDPServer->Active = true;


MS>В событии OnClick для Button1 выполняю передачу объекта серверу:

MS>
TMemoryStream *msS = new TMemoryStream();

MS>TPngImage *png = new TPngImage();
png->>Assign(Image1->Picture);

png->>SaveToStream(msS);
msS->>Position = soFromBeginning;

MS>TByteDynArray DynArray = RawToBytes(msS,msS->Size);

MS>delete png, msS;
MS>png = NULL, msS = NULL;

MS>UDPClient->SendBuffer(DynArray);


MS>Передача проходит на "ура". Теперь обрабатываю событие OnUDPRead:

MS>
void __fastcall TForm1::UDPServerUDPRead(TIdUDPListenerThread *AThread, TBytes AData,
MS>                    TIdSocketHandle *ABinding)
MS>{
MS>  TMemoryStream *msR = new TMemoryStream();
MS>  TPngImage *png = new TPngImage();

MS>  BytesToRaw(AData,msR,AData.Length);  // проблемое место
  msR->>Position = soFromBeginning;
  png->>LoadFromStream(msR);
MS>  Image2->Picture->Graphic = png;

MS>  delete png, msR;
MS>  png = NULL, msR = NULL;
MS>}


MS>Картинка появляется в Image2, но при закрытии формы возникает Access Violation.


MS>Функция BytesToRaw в третьем параметре требует int Size. Я передаю ей размер полученных данных (AData.Length) получаю всё тот же AV.

MS>Пробую передать размер TBytes (пробовал также для TByteDynArray):
MS>
BytesToRaw(AData,msR,sizeof(AData));

MS>В этом случае поток msR имеет нулевую длину и ссылается в NULL

MS>Пробовал работать с этой функцией без сетевой передачи (далее изменённый код OnClick для Button1):

MS>
  TMemoryStream *msS = new TMemoryStream();

MS>  TPngImage *png = new TPngImage();
  png->>Assign(Image1->Picture);

  png->>SaveToStream(msS);
  msS->>Position = soFromBeginning;

MS>  TByteDynArray DynArray = RawToBytes(msS,msS->Size);

MS>  BytesToRaw(DynArray,msS,sizeof(DynArray));
  msS->>Position = soFromBeginning;
  png->>LoadFromStream(msS);
MS>  mage2->Picture->Graphic = png;

MS>  delete png, msS;
MS>  png = NULL, msS = NULL;


MS>Тогда ошибок не возникает.


MS>Подскажите пожалуйста, что я делаю неправильно?


функции RawToBytes и BytesToRaw предназначены для простого копирования структуры в/из массив/а.
Внутри просто стоит memcpy.

в Вашем случае нужно использовать
WriteTIdBytesToStream и ReadTIdBytesFromStream;
Re[2]: BytesToRaw (Indy 10)
От: MikeSoft Украина msdn.at.ua
Дата: 23.06.10 09:46
Оценка:
Здравствуйте, icWasya, Вы писали:

W>функции RawToBytes и BytesToRaw предназначены для простого копирования структуры в/из массив/а.

W>Внутри просто стоит memcpy.

W>в Вашем случае нужно использовать

W>WriteTIdBytesToStream и ReadTIdBytesFromStream;

Спасибо Вам большое.
 
Подождите ...
Wait...
Пока на собственное сообщение не было ответов, его можно удалить.