Главная страница
Top.Mail.Ru    Яндекс.Метрика
Текущий архив: 2013.09.01;
Скачать: CL | DM;

Вниз

Как через 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;
Скачать: CL | DM;

Наверх




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


2-1356079437
Женя
2012-12-21 12:43
2013.09.01
Квадратное уравнение


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


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


2-1355837667
LDV
2012-12-18 17:34
2013.09.01
поиск дубликатов в таблице бд