Форум: "Начинающим";
Текущий архив: 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