Top.Mail.Ru
Мастера DELPHI, Delphi programming community Титульная страница Поиск, карта сайта Написать письмо 
| Новости | Поиск | FAQ | Статьи | Книги | Новости VCL |
| Форумы ЧАТ | Орешник | KOL и MCK |
Форумы -» Основная («Начинающим»)/ Базы / WinAPI / Компоненты / Сети / Media / Игры / Corba и COM / KOL / FreePascal / .Net / Прочее / RSDN.ORG

« предыдущая ветвь | форум | следующая ветвь »

Вопрос по TCP/IP а может я вообще ничего не понимаю. [D5, Win95/98]


Страницы:   1 2

arhis ©   (2004-02-04 12:58:00) 

В общем или я не догоняю чего-то в основах или не вижу элементарного.

Сервер посылает через сокет данные (1 байт: команда, 2-5 байт размер пакета без первых пяти, дальше идет дин массив из string[50]):

var command : byte;
p : ^LongInt;
buf :array of string[50];

под buf уже взяли из кучи и записали туда данные.
lenn - количесвто элементов массива.

Command:=3;
MySize:=(lenn)*51;
GetMem(buffer,5+MySize);
pBytearray(buffer)^[0]:=3;
p:=pointer(integer(buffer)+1);
p^:=MySize;
GetMem(pBuf,MySize);
pBuf^:=buf;
move(pBuf^,pointer(integer(buffer)+5)^,mySize);
freemem(pBuf,MySize);
label1.Caption:=IntToStr(Socket.SendBuf(buffer^,5+MySize));

Клиент из первого пакета берет команду читает размер и начинает прием:

ONREAD

var
bufferg : pointer;
resbuf : pointer;

rbuffer : TMemoryStream;
fff : array of string[50];

под поток из кучи взяли при инициализации программы, MylocalSize,bufsize,receiving глобальная переменная.

firstpacket:=false;
BlockSize:=Socket.ReceiveLength;
Getmem(bufferg,BlockSize);
Socket.Receivebuf(bufferg^,BlockSize);

if not(Receiving) then
 begin
  command:=pByteArray(bufferg)^[0];
  if Command = 3 then
   begin
    BufSize:=pLongInt(integer(bufferg)+1)^;
    MyLocalSize:=BlockSize-5;
    Receiving:=true;
    firstPacket:=true;
    rbuffer.Clear;    
    rBuffer.SetSize(BufSize);
    rBuffer.position:=0;
    rBuffer.write(pointer(integer(bufferg)+5)^,BlockSize-5);
   end;

if not(firstpacket) then
 begin
  MyLocalSize:=MyLocalSize+BlockSize;
  rBuffer.write(bufferg^,BlockSize);
 end;
if MyLocalSize=BufSize then
 begin
  met:=MyLocalSize div 51;
  SetLength(resBuf,met);
  Receiving:=false;
  getmem(fff,bufSize);
  rBuffer.position:=0;
  rBuffer.read(fff^,BufSize);
  move(fff^,pointer(resbuf)^,BufSize);
end;

freemem(bufferg,blockSize);

Команду и размер считываем правильно.
получаем ровно столько байт сколько послали.
вместо массива мусор.


Vladimir "Chainik"   (2004-02-11 20:48:00) [1]


> Polevi ©   (10.02.04 19:39) [37]
> >Verg ©   (10.02.04 19:24) [36]
> угу, и еще советы не стесняется давать
>
>
> Polevi ©   (10.02.04 19:40) [38]
> нет, ну это прямо в орешник просится, это ктоже его так
> обманул то ?


"Дети выразим Вове всеобщее презрение... Фууууу!"
"Приговариваем к трем годам растрела"
"Распни его! Распни..."

НЕ СУДИ И НЕ СУДИМ БУДЕШЬ
Можно было бы сказать: "Владимир ты не прав..."


> > Ермак ©   (08.02.04 11:47) [32]
> > Лучше всего не использовать вообще динамич массивы.
> > Только ГетМем и ФриМем.


Был неправ! Приношу Вам свои извинения!
Уважаемый модератор прошу удалить сообщение [35]

Маленькая ремарка по работе данного форума, прошу всех участников не обижаться и не принимать близко к сердцу нижеследующее.
На вопрос:
arhis   (04.02.04 14:19) [15]
Подскажите где. я неправильно оращаюсь к массиву.


Можно было бы ответить наподобие [30] и не углубляться в устроство памяти переменных, хотя за структуру ДМ Спасибо, очень интересно.
И пожалуйста поменьше эмоций, все таки серьёзные люди.


Vladimir "Chainik"   (2004-02-11 17:33:00) [2]

Книжка умная!!!


Polevi   (2004-02-10 19:40:00) [3]

нет, ну это прямо в орешник просится, это ктоже его так обманул то ?


Polevi   (2004-02-10 19:39:00) [4]

>Verg ©   (10.02.04 19:24) [36]
угу, и еще советы не стесняется давать


Verg   (2004-02-10 19:24:00) [5]


> 2.Лимит для этих функций насколько мне известно составляет
> 64 Кило, плюс захламляет стек указателями на переменные
> (Stack Overlow).


????


Vladimir "Chainik"   (2004-02-10 14:53:00) [6]


> Ермак ©   (08.02.04 11:47) [32]
> Лучше всего не использовать вообще динамич массивы.
> Только ГетМем и ФриМем.

Совсем забыл. Маленькая ремарка:
1.GetMem и FreeMem так ли они в данной задаче необходимы?
2.Лимит для этих функций насколько мне известно составляет 64 Кило, плюс захламляет стек указателями на переменные (Stack Overlow).


Vladimir "Chainik"   (2004-02-10 14:46:00) [7]


> Anatoly Podgoretsky ©   (08.02.04 12:16) [33]
> Плюнь ты на динамические массивы и указатели, работай со
> статическими, а потом через пару лет вернить к ним, если
> получится. Ну не понимаешь ты на данном этапе.


А вот этого, я бы Вам не советовал. "Под лежачий камень, и вода не течет"
В ответе [30] описанно вполне ясно, сам мучался со статическими массивами размером 3 000 000 элементов, пока в одной умной книжке не нашел несколько строк по работе с ДМ [30]. Сейчас у меня все работает размером вплоть до 4 Гигов, произвольной размерностью, и без проблем, если конечно в коде не выскакиваю за границы определения ДМ, но для этого и существуют функции Low() и High(), а самими данными как с данными из обычных статических масивов тех же массо-габаритных параметров. Исключение составляет работа с массивом через указатели, но и здесь нет ничего сложного для перехода на них (указатели)


Anatoly Podgoretsky   (2004-02-08 12:16:00) [8]

Плюнь ты на динамические массивы и указатели, работай со статическими, а потом через пару лет вернить к ним, если получится. Ну не понимаешь ты на данном этапе.


Ермак   (2004-02-08 11:47:00) [9]

Лучше всего не использовать вообще динамич массивы.
Только ГетМем и ФриМем.
А, кстати, заголовок динамич массива находится не в том месте, куда указывает указатель на этот массив, а перед ним. То есть
/заголовок/-сюда указывает указатель-/данные/


Verg   (2004-02-04 17:30:00) [10]


> И уж я думаю что вы сразу догадались где он.


А тебе не кажется, что нехорошо таким образом разбазаривать чужое время?

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

Иниыми словами ты хочешь сказать, что у тебя все правильно, а глючит TCP/IP.

Я не собираюсь тратить время и доказывать тебе, что сокеты работаю абсолютно так, как написано в документации.

Теперь уж ты убеди меня, что первая принятая порция обязательно будет содержать не менее чем размер заголовка пакет число байт.
Или там какой-нибудь if потерялся при копировании?
Нет, я могу "догадаться" как должна выглядеть процедура приема апакетов чере сокет, только не говори, что правлиьный твОй вариант был потерян при копировании.


Vladimir Chainik   (2004-02-04 17:26:00) [11]

Для структуры типа buf :array of string[50];применнение команд разименования(обращение типа buf^), GetMem(buf,...),FreeMem(buf,...),в D5 и выше считаются недопустимыми,
и приводят только к передаче содержимого стека (то бишь только указателей на переменную).
Для определения вышеуказанного массива необходимо сделать следующее:

buf:=nil; {обнуляется указатель масссива (освобождается память выделенная под массив) }
SetLength(buf,кол-во эл-тов);{если количество:=0, то также происходитт освобождение памяти выделеннной под массив, в противном случае выделяется память размером "Кол-во эл-тов"}

далее обращение только buf[i] , где i:=0..N-1. Причем Все это справедливо для всех типов buf[i] [variant...object] смотря что определено в заголовке VAR buf:array of тип;

Чтобы измерить длину этого массива
lenn:=length(buf);
StartIndex:=Low(buf);
EndIndex:=High(buf);


arhis   (2004-02-04 17:16:00) [12]

end потерян при копировании. А вас вообще не очень смутило отсутсвие остального синтаксиса? И уж я думаю что вы сразу догадались где он.

> if not(Receiving) then
>  begin //Где енд от него?
>   command:=pByteArray(bufferg)^[0];
>   if Command = 3 then
>    begin
>     BufSize:=pLongInt(integer(bufferg)+1)^;
>     MyLocalSize:=BlockSize-5;
>     Receiving:=true;
>     firstPacket:=true;
>     rbuffer.Clear;    
>     rBuffer.SetSize(BufSize);
>     rBuffer.position:=0;
>     rBuffer.write(pointer(integer(bufferg)+5)^,BlockSize-5);
>    end; // От какого begin-а end?
end;

> if not(firstpacket) then
>  begin
>   MyLocalSize:=MyLocalSize+BlockSize;
>   rBuffer.write(bufferg^,BlockSize);
>  end;
> if MyLocalSize=BufSize then
>  begin


Verg   (2004-02-04 17:07:00) [13]

Еще раз, для особо одаренных:


> if not(Receiving) then
>  begin //Где енд от него?
>   command:=pByteArray(bufferg)^[0];
>   if Command = 3 then
>    begin
>     BufSize:=pLongInt(integer(bufferg)+1)^;
>     MyLocalSize:=BlockSize-5;
>     Receiving:=true;
>     firstPacket:=true;

>     rbuffer.Clear;    
>     rBuffer.SetSize(BufSize);
>     rBuffer.position:=0;
>     rBuffer.write(pointer(integer(bufferg)+5)^,BlockSize-5);
>    end; // От какого begin-а end?
>
> if not(firstpacket) then
>  begin
>   MyLocalSize:=MyLocalSize+BlockSize;
>   rBuffer.write(bufferg^,BlockSize);
>  end;
> if MyLocalSize=BufSize then
>  begin


Verg   (2004-02-04 17:02:00) [14]


> arhis   (04.02.04 16:54) [25]
> > Verg
> Да он выполняется.
>
> if Command = 3 then
>   begin
>    BufSize:=pLongInt(integer(bufferg)+1)^;
>    MyLocalSize:=BlockSize-5;
>    Receiving:=true;
>    firstPacket:=true;


Да ? А дальше...


> if not(firstpacket) then


arhis   (2004-02-04 16:59:00) [15]

По поводу TMemoryStream. Мне было лень самому объединять пакеты в одно целое поэтому я решил воспользоваться потоком.

В предидущем ответе я несколько поторопился участок кода выполняется всегда если только это не первый пакет.


arhis   (2004-02-04 16:54:00) [16]

> Verg
Да он выполняется.

if Command = 3 then
  begin
   BufSize:=pLongInt(integer(bufferg)+1)^;
   MyLocalSize:=BlockSize-5;
   Receiving:=true;
    firstPacket:=true;
   rbuffer.Clear;    
   rBuffer.SetSize(BufSize);
   rBuffer.position:=0;
   rBuffer.write(pointer(integer(bufferg)+5)^,BlockSize-5);
  end;


Verg   (2004-02-04 16:43:00) [17]


> >Verg
> Мы говорим о разных вещах. Вы говорите о том как хорошо
> пользоваться StringList`ом а я говорю,


Вот ты такой же рассеянный и в кодировании. Скрестили ежа с ужом.
Я не говорил ни о каких StringList-ах.

Усложнил себе жизнь многочисленными нетипизированными поинтерами, ты производишь преобразования их типов к указателям на динамические массивы, не проверяешь результаты выполнений ф-ций над сокетами, бесконечные совершенно бесцельные пересылки массивов из памяти в память, умудрилcя приплести сюда на кой-то ляд TMemoryStream, какие-то сомнительные флаги..... Короче как спецмально, чтобы запутаться "огрести" как можно больше глюков.


>
> if not(Receiving) then
>  begin
>   command:=pByteArray(bufferg)^[0];
>   if Command = 3 then
>    begin
>     BufSize:=pLongInt(integer(bufferg)+1)^;
>     MyLocalSize:=BlockSize-5;
>     Receiving:=true;
>     firstPacket:=true;
>     rbuffer.Clear;    
>     rBuffer.SetSize(BufSize);
>     rBuffer.position:=0;
>     rBuffer.write(pointer(integer(bufferg)+5)^,BlockSize-5);
>    end;
>
> if not(firstpacket) then
>  begin
>   MyLocalSize:=MyLocalSize+BlockSize; Как думаешь этот участо кода (что, после THEN у тебя кода-нибудь выполняетс?>   rBuffer.write(bufferg^,BlockSize);
>  end;


Digitman   (2004-02-04 16:36:00) [18]


> Где можно найти инфу по этим заголовкам?


в модуле System.pas
и на сайте у Борланда


> Вы говорите о том как хорошо пользоваться StringList`ом
> а я говорю, что он для меня неприемлем


почему ? можешь привести веские конкретные аргументы в пользу "неприемлемости" ?


arhis   (2004-02-04 16:23:00) [19]

> Digitman
Интересно зачем изъясняться намеками?

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

Где можно найти инфу по этим заголовкам?

>Verg
Мы говорим о разных вещах. Вы говорите о том как хорошо пользоваться StringList`ом а я говорю, что он для меня неприемлем. Как я могу бросить динамический массив, когда именно его мне и надо передать, потому что все данные хранятся в них.

> getMem(point,Mysize);
>     move((Pointer(integer(buffer)+5)^),point^,MySize);
>     for met:=1 to 5 do
>        StringGrid1.cells[0,met]:=arrStr(point^)[met-1];

Может я и упертый но, опять же хочу обратить внимание на эти строки. Почему программа работает?

Я беру память из кучи и именно столько сколько в тупую весит дин массив без заголовков:

getmem(point,MySize);

копирую туда данные из другого буфера (buffer), который тоже нетипизирован (массивы прощайте) , причем я просто скопировал в него дин массив без всяких заголовков количесвто перенесенных байт равно тупой длине моего массива без заголовков:

move((Pointer(integer(buffer)+5)^),point^,MySize);

А дальше простое приведение типов и все работает:

for met:=1 to 5 dо
StringGrid1.cells[0,met]:=arrStr(point^)[met-1];

вот что мне не понять.


Verg   (2004-02-04 15:52:00) [20]


> arhis   (04.02.04 15:45) [19]
> Ну и как я буду резервировать место в статическом массиве
> под элементы, когда в одном запросе их может быть 100 а
> в другом 10000000000000.


Я ж тебе показал. Ничего я не резервировал. Резервирование произошло где-то раньше, где было выделение памяти в перемнную buffer, которая была использована при приеме пакета ф-цией ReceiveBuf(Buffer^, MySize).


Страницы:   1 2

Наверх

Титульная страница Поиск, карта сайта Написать письмо