Главная страница
    Top.Mail.Ru    Яндекс.Метрика
Форум: "Начинающим";
Текущий архив: 2013.09.01;
Скачать: [xml.tar.bz2];

Вниз

Как через TMemoryStream и IdTCPServer передать переменную Record   Найти похожие ветки 

 
oam333 ©   (2012-12-18 17:07) [0]

Есть переменная типа Record. В ней два параметра: типа Integer и типа TMemoryStream.
Как полученную переменную Record передать клиенту через IdTCPServer, чтобы на клиенте разобрать этот поток обратно в Record?

 TPack = Record
   block_num   : integer;
   pic_content : TMemoryStream;
 end;

var stream_old: TPack;

procedure TForm1.Button1Click(Sender: TObject);
begin
  stream_old.block_num := 10;
  stream_old.pic_content := TMemoryStream.Create;
end;

procedure TForm1.IdTCPServer1Execute(AThread: TIdPeerThread);
var strText: string;
   i: integer;
   ScreenCopy: TCanvas;
   gr: TBitmap;
   rcDest, rcSource: TRect;
   PNG: TPNGObject;
begin
  rcSource := Screen.DesktopRect; //исходный размер картинки
  rcDest := Rect(0, 0, 100, 100); //конечный размер картинки
  ScreenCopy := TCanvas.Create;
  ScreenCopy.Handle := GetDC(0);
  gr:= TBitmap.Create;
  gr.Height := 100;
  gr.Width := 100;
  gr.Canvas.CopyRect(rcDest, ScreenCopy, rcSource);

  PNG := TPNGObject.Create;
  PNG.Assign(gr);
  PNG.SaveToStream(stream_old.pic_content);
  PNG.Free;
  gr.Free;

  AThread.Connection.WriteStream(stream_old, true, true);
end;



Вот как в предпоследней строке передать stream_old?


 
Медвежонок Пятачок ©   (2012-12-18 17:13) [1]

Вот так и передать.
Но перед тем как, - встать в начало стрима


 
брат Птибурдукова   (2012-12-18 17:36) [2]


> AThread.Connection.WriteStream(stream_old, true, true);
Ну что-то типа такого:
AThread.Connection.WriteStream(stream_old.block_num, true, true);
AThread.Connection.WriteStream(stream_old.pic_content.memory^, true, true);
...ну там ещё по-любому должна быть какая-то версия WriteStream, позволяющая задавать размер записываемой области памяти.

ЗЫ. А зачем тут запись? Почему бы block_num не пихать в тот же MemoryStream?


 
oam333 ©   (2012-12-19 08:36) [3]


> Вот так и передать.
> Но перед тем как, - встать в начало стрима

stream_old типа Record и не может быть передан в чистом виде как поток, т.к. не типа TMemoryStream.


 
oam333 ©   (2012-12-19 08:38) [4]

брат Птибурдукова

> ЗЫ. А зачем тут запись? Почему бы block_num не пихать в
> тот же MemoryStream?

Хотел именно за один прием (за один WriteStream) передать все значения. Или такое все же невозможно?


 
oam333 ©   (2012-12-19 08:46) [5]

брат Птибурдукова
пост опубликовал и только потом понял смысл вопроса.
Да, именно в MemoryStream я бы и хотел запихнуть block_num, но нихрена понять не могу как. Много чего перечитал в гугле, но все равно не пойму. Понятно, что нужно пользоваться seek, но возникает вопрос:
если вставить в начало потока значение block_num, а вслед за ним значение pic_content, то как я потом смогу разобрать на клиенте этот поток обратно на block_num и pic_content? Откуда я узнаю длину block_num и длину pic_content, чтобы вытащить значения из потока?


 
Медвежонок Пятачок ©   (2012-12-19 09:04) [6]

Хотел именно за один прием (

За один прием можно, но не в твоем случае.

Откуда я узнаю длину block_num
В смысле ты боишься, что не сможешь узнать длину интегера?


 
oam333 ©   (2012-12-19 09:16) [7]

Медвежонок Пятачок

> В смысле ты боишься, что не сможешь узнать длину интегера?

Как говорится, прозрение! Ведь block_num это ж integer. Меня почему-то переклинило, и я думал, что если block_num=5, то длина одна, а если block_num=1234, то длина другая. Почему-то подумал, что нужно считать каждую цифру в значении. Мда.. Переработал.
Сейчас чего-нибудь наваяем.
Сенкс!


 
Сергей М. ©   (2012-12-19 10:16) [8]

передатчик:

ms := TMemoryStream.Create;
try
 ms.WriteBuffer(stream_old.block_num, sizeof(block_num));
 ms.WriteBuffer(stream_old.pic_content.memory^,   stream_old.pic_content.Size);
 AThread.Connection.WriteStream(ms, true, true);
finally
 ms.Free;
free;


приемник:

pack.block_num := AThread.Connection.ReadInteger;
AThread.Connection.ReadStream(pack.pic_content, -1, true);



 
Anatoly Podgoretsky ©   (2012-12-19 13:01) [9]

> oam333  (19.12.2012 08:46:05)  [5]

Хочешь узнать передавай в потоке


 
oam333 ©   (2012-12-19 16:44) [10]

Блин, немного переделал, но вылетает Access Violation

передатчик:

 TPack = Record
   block_col   : integer;
   block_row   : integer;
   pic_content : TMemoryStream;
 end;

procedure TForm1.IdTCPServer1Execute(AThread: TIdPeerThread); //отправка блоков
var stream_new: array of TPack;
    status: string;
    ms: TMemoryStream;
    i: integer;
begin
<...>
// формирую все элементы stream_new
// что-то типа:
// stream_new[0...99].block_col:= 10...1000;
// stream_new[0...99].block_row:= 10...1000;
// stream_new[0...99].pic_content.LoadFromStream(какой-то стрим);
<...>
        for i:=0 to 99 do
           begin
               ms:=TMemoryStream.Create;
                try
                  status:="block";
                  ms.Write(status, SizeOf(status));
                  ms.Write(stream_new[i].block_col, SizeOf(stream_new[i].block_col));
                  ms.Write(stream_new[i].block_row, SizeOf(stream_new[i].block_row));
                  ms.Write(pointer(stream_new[i].pic_content)^, stream_new[i].pic_content.Size);
                 
{                   ms.WriteBuffer(stream_new[i].block_col, sizeof(stream_new[i].block_col));
                  ms.WriteBuffer(stream_new[i].block_row, sizeof(stream_new[i].block_row));
                  ms.WriteBuffer(stream_new[i].pic_content.memory^, stream_new[i].pic_content.Size); }
                  AThread.Connection.WriteStream(ms, true, true);
                finally
                  ms.Clear;
//                   ms.Free;
                end;
           end;


приемник:

procedure TForm1.Button1Click(Sender: TObject);
var stream: TMemoryStream;
    status: string;
begin
  repeat
    status:="";
    IdTCPClient1.ReadStream(stream);
    stream.Position := 0;
    stream.Read(status, sizeof(status));
     if (status = "block") then // здесь вылетает Access Violation
      begin
        stream.Read(block_col, sizeof(integer));
        stream.Read(block_row, sizeof(integer));
        stream.Read(pic_content, pic_content.Size);

        //дальше обработка полученных данных
        <...>
      end;
     stream.Clear;
   until status = "end";
   stream.Free;
end;


 
oam333 ©   (2012-12-19 17:05) [11]

Опечатался немного выше.
Если в передатчике в блоке try написано (как выше)
ms.Write(status, SizeOf(status));
то в приемнике в status прилетает
#0#0#0#0
Если указано
ms.Write(Pointer(status)^, SizeOf(status));
то в приемнике вылетает в Access Violation на строке
if (status = "block") then


 
Германн ©   (2012-12-19 17:19) [12]

А так не пробовал?
ms.Write(status[1], Length(status));


 
MBo ©   (2012-12-19 17:21) [13]

строка status  - указатель, sizeof(status) = 4, и в поток пишется не содержимое строки, а адрес, который приёмнику не нужен.
Нужно писать в поток сначала длину строки (Length), потом тело PChar(status)^


 
oam333 ©   (2012-12-20 12:45) [14]

Все равно вылетает Access Viaolation...
попробовал так:

передатчик:
                  status_length:=Length(status);
                  ms.Write(status_length, SizeOf(status_length));
                  ms.Write(PChar(status)^, Length(status)*SizeOf(status));
//                   ms.Write(PChar(status)^, Length(status); - так не прокатывает
//                   ms.Write(status[1], Length(status)*SizeOf(status)); - так не прокатывает
//                   ms.Write(status[1], Length(status)); - так не прокатывает
                  ms.Write(stream_new[i].block_col, SizeOf(stream_new[i].block_col));
                  ms.Write(stream_new[i].block_row, SizeOf(stream_new[i].block_row));
                  ms.Write(pointer(stream_new[i].pic_content)^, stream_new[i].pic_content.Size);


приемник:
     IdTCPClient1.ReadStream(stream);
     stream.Position := 0;
     stream.Read(status_length, sizeof(status_length));
     SetLength(status, status_length);
     stream.Read(status, status_length*sizeof(string));

     if (status = "block") then //здесь снова Access Violation
       <...>


Мышкой навожу на переменную status в последней строке кода приемника (выше), пишет Inaccesible Value.

Скоро начну психовать...


 
oam333 ©   (2012-12-20 12:54) [15]

Нашел косяк.
В приемнике, где читаю саму строку вместо

stream.Read(status, status_length*sizeof(string));

нужно писать указать на status, а не саму переменную

stream.Read(Pointer(status)^, status_length*sizeof(string));


 
брат Птибурдукова   (2012-12-20 13:04) [16]


> status_length*sizeof(string)
Бред, отсюда и AV. status_length * SizeOf(Char). Ну или status_length * SizeOf(status[0])


 
oam333 ©   (2012-12-20 16:21) [17]

Я, видимо, замучаю всех. Эти Access Violation меня в конец выбесят..
Теперь при чтении стрима, который лежит в pic_content

Передатчик:

               ms:=TMemoryStream.Create;
                try
                  status:="block"; //block
                  status_length:=Length(status);
                  ms.Write(status_length, SizeOf(status_length));
                  ms.Write(Pointer(status)^, status_length*SizeOf(Char));

                  ms.Write(stream_new[i].block_col, SizeOf(stream_new[i].block_col));
                  ms.Write(stream_new[i].block_row, SizeOf(stream_new[i].block_row));

                  pic_content_length:=stream_new[i].pic_content.Size; // размер картинки
                  ms.Write(pic_content_length, SizeOf(pic_content_length)); // пишем размер картинки
                  ms.Write(pointer(stream_new[i].pic_content)^, stream_new[i].pic_content.Size); //пишем саму картинку

                  AThread.Connection.WriteStream(ms, true, true); // отправляем
                finally
                  ms.Clear;
//                   ms.Free;
                end;


Приемник:


pic_content: TMemoryStream;
Fs: TFileStream;

     IdTCPClient1.ReadStream(stream);
     stream.Position := 0;
     stream.Read(status_length, sizeof(status_length));
     SetLength(status, status_length);
     stream.Read(Pointer(status)^, status_length*SizeOf(Char));

     if (status = "block") then
      begin
        stream.Read(block_col, sizeof(integer));
        stream.Read(block_row, sizeof(integer));

        stream.Read(pic_content_length, sizeof(pic_content_length)); //читаем размер картинки
        pic_content.Size:=pic_content_length; // выделяем переменной память

        stream.Read(Pointer(pic_content)^, pic_content_length); // читаем картинку

        Fs := TFileStream.Create("out.bin", fmCreate, fmShareDenyWrite);
        Fs.CopyFrom(pic_content, pic_content.Size); // и вот тут Access Violation
        Fs.Free;


Тяжело мне даются потоки... уже упарился...


 
брат Птибурдукова   (2012-12-20 17:25) [18]


> ms.Write(Pointer(status)^
Что за фиговина? Передавай @status[1] или PChar(status).


> pointer(stream_new[i].pic_content)^
Да и это фигня какая-то. pic_content какого типа?


 
MBo ©   (2012-12-20 18:41) [19]

>Что за фиговина? Передавай @status[1] или PChar(status).
не, там var, а не указатель

>и вот тут Access Violation
позицию читаемого потока надо выставить (в 0, наверно)


 
oam333 ©   (2012-12-20 23:08) [20]

брат Птибурдукова

> ms.Write(Pointer(status)^, status_length*SizeOf(Char));

эта хрень мне точно выдает то, что мне нужно, а именно в данном случае слово "block". Здесь пишем указатель на строку status длиной "количество символов в строке * размер чара".


> pointer(stream_new[i].pic_content)^
> Да и это фигня какая-то. pic_content какого типа?

stream_new - это массив of Record
stream_new[i].pic_content: TMemoryStream

MBo

> позицию читаемого потока надо выставить (в 0, наверно)

попробовал после
stream.Read(Pointer(pic_content)^, pic_content_length);
добавить
pic_content.Position:=0;
и отладчик показал на этой добавленной строке: "Project Client.exe raised exception with message "Priveleged instruction". Process stopped. Use Step or Run to continue."


 
брат Птибурдукова   (2012-12-20 23:31) [21]


> stream_new[i].pic_content: TMemoryStream
Тогда  ms.Write(stream_new[i].pic_content.memory, stream_new[i].pic_content.Size);


 
oam333 ©   (2012-12-20 23:52) [22]

брат Птибурдукова
ага, в этом был косяк. Только крышка ^ после memory нужна. Тогда работает.
Большое спасибо!
Ваяем дальше.



Страницы: 1 вся ветка

Форум: "Начинающим";
Текущий архив: 2013.09.01;
Скачать: [xml.tar.bz2];

Наверх





Память: 0.52 MB
Время: 0.003 c
15-1364240820
Дмитрий С
2013-03-25 23:47
2013.09.01
Нет ли в дельфи каких-нибудь волшебных констант?


15-1364321098
TStas
2013-03-26 22:04
2013.09.01
Что такое искусственный интелект?


15-1364278811
N.Cage
2013-03-26 10:20
2013.09.01
Amd vs Intel


15-1354481915
Конь Як
2012-12-03 00:58
2013.09.01
Веб программирование


15-1364579022
alexdn
2013-03-29 21:43
2013.09.01
Давненько о космосе не было





Afrikaans Albanian Arabic Armenian Azerbaijani Basque Belarusian Bulgarian Catalan Chinese (Simplified) Chinese (Traditional) Croatian Czech Danish Dutch English Estonian Filipino Finnish French
Galician Georgian German Greek Haitian Creole Hebrew Hindi Hungarian Icelandic Indonesian Irish Italian Japanese Korean Latvian Lithuanian Macedonian Malay Maltese Norwegian
Persian Polish Portuguese Romanian Russian Serbian Slovak Slovenian Spanish Swahili Swedish Thai Turkish Ukrainian Urdu Vietnamese Welsh Yiddish Bengali Bosnian
Cebuano Esperanto Gujarati Hausa Hmong Igbo Javanese Kannada Khmer Lao Latin Maori Marathi Mongolian Nepali Punjabi Somali Tamil Telugu Yoruba
Zulu
Английский Французский Немецкий Итальянский Португальский Русский Испанский