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

Вниз

Непонятная проблема с буфером в Инди компоненте   Найти похожие ветки 

 
h0use ©   (2003-11-24 15:32) [0]

Есть сервер, который слушает порт:

Msg:=AThread.Connection.ReadLn;
if Msg<>">>>" then exit;
AThread.Connection.ReadBuffer(CommBlock,SizeOf(CommBlock));

Есть клиент, котрый шлет на сервер блок данных:

function TfmMain.SendMsg(AMsg:TCommBlock): boolean;
begin
Result:=False;
try
if TCPClient.Connected then
begin
TCPClient.WriteLn(">>>");
TCPClient.WriteBuffer(AMsg,SizeOf(AMsg));
Result:=True;
end;
except
on e: Exception do
ShowMessage("Send Error: "+e.Message);
end; // try/except

Есть сам покет данных одинаковый для сервера и клиента:

type
TCommBlock = record // the Communication Block used in both parts (Server+Client)
Command : Char;
Argument1 : String[10];
Argument2 : WideString;
Msg : WideString;
end;


При том, что при дебаге клиент шлет нормальную инфу, сервер получает тольуо первый и второй аргумент записи нормально, а третий и четвертый - белеберда. В чем ботва?


 
Reindeer Moss Eater ©   (2003-11-24 15:36) [1]

Эти аргументы - указатели.
На сервере они так же полезны, как и седло корове


 
h0use ©   (2003-11-24 15:48) [2]

Т.е. ты хочешь сказать, что char и string передается как есть, а widestring передается как указатель?


 
Reindeer Moss Eater ©   (2003-11-24 15:49) [3]

Он и есть указатель.

http://delphimaster.net/view/6-1069393748/


 
Digitman ©   (2003-11-24 15:53) [4]


> h0use


ansistring и widestring - да, как указатели ... почему тебя это шокирует ?


 
h0use ©   (2003-11-24 15:58) [5]

А как же мне их передавать?


 
Reindeer Moss Eater ©   (2003-11-24 15:59) [6]

А зачем передавать ИХ?


 
Reindeer Moss Eater ©   (2003-11-24 16:00) [7]

А ссылка для кого вообще приведена была?


 
Digitman ©   (2003-11-24 16:05) [8]


> h0use


> как же мне их передавать


как компилятор хранит - так и передавай : сначала размер, потом данные


 
h0use ©   (2003-11-24 16:27) [9]

Если честно, то я слабо понял, что там происходит (в примере по ссылке)


 
Reindeer Moss Eater ©   (2003-11-24 16:29) [10]

Тогда просто замени свои WideString на ShortString


 
Digitman ©   (2003-11-24 16:35) [11]


> я слабо понял


это печально

и не поймешь, пока не бросишь слепые эксперименты и не обратишься к соотв.литературе ... либо не начнешь задавать КОНКРЕТНЫЕ вопросы, мол, объясните . почему это именно так , а не иначе


 
sanya-spb   (2003-11-24 16:49) [12]

как вариант может и PChar сойти.. я так думаю


 
Reindeer Moss Eater ©   (2003-11-24 16:51) [13]

В качестве того же указателя, но "в профиль" ?


 
h0use ©   (2003-11-24 16:56) [14]

Делаю вот так:

GetMem(p,SizeOf(Char)+3*SizeOf(Cardinal)+StrLen(AMsg.Argument1)+StrLen(AMsg.Argument2)+StrLen(AMsg.Msg));
pC:=p;
pC^:=AMsg.Command;
Inc(pC);
pLen1 := Pointer(pC);
pLen1^:=StrLen(AMsg.Argument1);
Inc(PLen1);
StrCopy(PChar(PLen1),AMsg.Argument1);
pLen2 := Pointer(pLen1);
pLen2^:=StrLen(AMsg.Argument2);
Inc(PLen2);
StrCopy(PChar(PLen1),AMsg.Argument2);
pLen3 := Pointer(pLen2);
pLen3^:=StrLen(AMsg.Msg);
Inc(PLen3);
StrCopy(PChar(PLen1),AMsg.Msg);
TCPClient.WriteLn(">>>");
TCPClient.WriteBuffer(p^,SizeOf(Char)+3*SizeOf(Cardinal)+StrLen(AMsg.Argument1)+StrLen(AMsg.Argument2)+StrLen(AMsg.Msg)) ;
Result:=True;

Пришлось поменять в структуре все виды срок на PChar, так как я не додумался как адаптировать пример по ссылке под widestring, но все равно не работает!


 
sanya-spb   (2003-11-24 17:05) [15]

а зачем тебе так надо открытые строки использовать?
неужели нельзя ShortString взять?

если нельзя то можно заменить строку на StringStream или нечто подобное...


 
h0use ©   (2003-11-24 17:14) [16]

Впринципе логично, можно и не использовать...буду думать дальше...


 
Reindeer Moss Eater ©   (2003-11-24 17:17) [17]

//Распределил память под сообщение
GetMem(p,SizeOf(Char)+3*SizeOf(Cardinal)+StrLen(AMsg.Argument1)+StrLen(AMsg.Argument2)+StrLen(AMsg.Msg));

//Записал символ команды
pC:=p;
pC^:=AMsg.Command;
Inc(pC);

//После символа команды записал длину первого аргумента
pLen1 := Pointer(pC);
pLen1^:=StrLen(AMsg.Argument1);
//После длины первого аргумента записал строку первого аргумента
Inc(PLen1);
StrCopy(PChar(PLen1),AMsg.Argument1);

//Встал на начало строки первого аргумента
pLen2 := Pointer(pLen1);
//Испортил первые четыре символа строки первого аргумента, записав поверх их длину второго аргумента
pLen2^:=StrLen(AMsg.Argument2);
Inc(PLen2);
//Перешагнул через испорченные 4 первых байта строки первого аргумента и записал строку второго аргумента (поверх еще неиспорченных символов строки первого аргумента)
StrCopy(PChar(PLen1),AMsg.Argument2);
....

Ну и так далее


 
h0use ©   (2003-11-25 16:01) [18]

Ну так а как сделать правильно?


 
Reindeer Moss Eater ©   (2003-11-25 16:07) [19]

Очевидно, что правильно будет тогда, когда не будешь на очередном шаге портить содержимое памяти созданное предыдущим шагом.

А вообще тот конкретный пример был дан как иллюстрация передачи конкретной структуры. Её не предлагалось изменить, а была предложена подпорка, которая умеет передавать данные той первоначальной структуры.


 
h0use ©   (2003-11-25 16:57) [20]

Ну так объясните, плиз, если у меня конструкция

TCommBlock = packed record
Command : Byte;
Argument1 : Byte;
Argument2 : Byte;
Msg : String;
end;


И почему при аналогичной структуре в примерах Инди все работает без ухищрения с указателями?


 
Reindeer Moss Eater ©   (2003-11-25 17:04) [21]

Потому что там компилятор считает Msg короткой строкой.


 
h0use ©   (2003-11-25 17:06) [22]

т.е. если я напишу String[255] то все заработает?


 
h0use ©   (2003-11-25 17:09) [23]

И заработало! Блин, но так не честно! Нигде в хелпе по Делфе это не написано, а я угробил сутки для понимания проблемы :(


 
h0use ©   (2003-11-25 17:09) [24]

Забыл поблагодарить за помощь!


 
Reindeer Moss Eater ©   (2003-11-25 17:11) [25]

Что "все"?
У тебя и так все работает.
Все что ты просишь у компилятора.
Он создает отличный код, который передает ВСЕ, что ты его просишь передать (все до единого бита)

И пора понять, что есть короткие строки, все символы которых лежат внутри записи, и есть длинные строки, которые находятся в куче. И куча эта располагается далеко за пределами всех сегментов твоей программы (кода,данных,стека)


 
h0use ©   (2003-11-25 17:19) [26]

Просто провал в образовании, я всегда считал, что если у строки не указано кол-во символов, то это эквивалентно строке 255 символов т.е. String=String[255]. Оказалось что заблуждался, хоть и в хелпе не нашел информации.



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

Текущий архив: 2004.01.29;
Скачать: CL | DM;

Наверх




Память: 0.53 MB
Время: 0.016 c
1-93563
dima_matrix
2004-01-17 13:48
2004.01.29
Закрытие и уничтожение форм


1-93428
_none_
2004-01-16 15:29
2004.01.29
вывод графики через bitblt: мелькание (синхронизация?)


1-93576
Piroman
2004-01-17 07:56
2004.01.29
Событие OnPaint глючит?


3-93391
Andriy Tysh
2003-12-30 11:16
2004.01.29
DBGridEh.SumList


1-93577
новичок_из_сыктывкара
2004-01-17 07:18
2004.01.29
надо сделать дерганье мышки за пределами главной формы