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

Вниз

Вопрос по TCP/IP а может я вообще ничего не понимаю.   Найти похожие ветки 

 
arhis   (2004-02-04 12:58) [0]

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

Сервер посылает через сокет данные (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);

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


 
Reindeer Moss Eater ©   (2004-02-04 13:02) [1]

TCP тут ни с какого боку не при чем.
Работа с указателями и динамически выделенной памятью.


 
arhis   (2004-02-04 13:08) [2]

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

Для того чтобы проверить что я посылаю я при передаче извлекаю тот самый массив из общего буфера посланных данных и он прекрасно читается.


 
Reindeer Moss Eater ©   (2004-02-04 13:10) [3]

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

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

Это не обязательно то, что "пришло"


 
arhis   (2004-02-04 13:14) [4]

Размер первого пакета у меня всегда больше чем 5+51 байт, насколько я понимаю пакеты по TCPIP не могут обгонять друг друга. Читаем первый пакет: первый байт все в порядке комманда под номером три, 2-5 байты все в порядке размер массива в байтах в моем случае 40596, дальше бог знает что.


 
Digitman ©   (2004-02-04 13:33) [5]


> дальше бог знает что


потому что передаешь черт те что, ибо динамический массив пытаешься передать/принять как статический


 
Arhis   (2004-02-04 13:38) [6]

Объясните мне пожалуйста в чем я не прав.

Я беру массив переношу его содержимое в нетипизированный буфер, и этот буфер посылаю. Какая разница для протокола какие байты пересылать.


 
Digitman ©   (2004-02-04 13:49) [7]

и к чему такие сложности вообще ?

объяви тип

TPrefix = packed record
 Cmd: Byte;
 ParamSize: Integer;
end;

замени array of string[] на TStringList

теперь передавай (предполагается блок.режим):

var
 Prefix: TPrefix;
 List: TStrings;
 Param: String;
..

Prefix.Cmd := 3;
Param := List.Text;
Prefix.ParamSize := Length(Param);
Socket.SendBuf(Prefix, SizeOf(Prefix));
Socket.SendBuf(Param[1], Length(Param));

и принимай (предполагается блок.режим):

var
 Command: Byte;
 Prefix: TPrefix;
 List: TStrings;
 Param: String;
..

Socket.ReceiveBuf(Prefix, SizeOf(Prefix));
Command := Prefix.Cmd;
SetLength(Param, Prefix.ParamSize);
Socket.ReceiveBuf(Param[1], Length(Param));
List.Text := Param;

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


 
Digitman ©   (2004-02-04 13:51) [8]


> беру массив переношу его содержимое


я не вижу в твоем коде определения фактического размера данных, занимаемых дин.массивом


 
Verg ©   (2004-02-04 13:59) [9]

var Rcvd, RecOnce : integer;  
   P : pchar;

begin
 
 Rcvd := 0;

 P := @Prefix;
 while Rcvd < sizeof(Prefix) do
 begin
   RecOnce := Socket.ReceiveBuf((P+Rcvd)^, SizeOf(Prefix)-Rcvd);
   if RecOnce <=0 then
      Exit; // ERROR !!!
   inc( Rcvd, RecOnce );
 end;

 Rcvd := 0;
 SetLength(Param, Prefix.ParamSize);
 P := @Param[1];
 While Rcvd < Prefix.ParamSize do
 begin
   RecOnce := Socket.ReceiveBuf((P+Rcvd)^, Prefix.ParamSize - Rcvd);
   if RecOnce <=0 then
      Exit; // ERROR !!!
   inc( Rcvd, RecOnce );
 end;
 List.Text := Param;


 
Verg ©   (2004-02-04 14:05) [10]

Хотя что-либо вообще трудно понять в том "месиве" из всяческих поинторов, но по-моему, у него сокет асинхронный. А вообще, черт знает что...


 
arhis   (2004-02-04 14:10) [11]

вот это определение размера массива
lenn - количнсвто элементов массива.

MySize:=(lenn)*51;


 
Digitman ©   (2004-02-04 14:10) [12]


> Verg ©   (04.02.04 14:05) [10]


угу... понаворочено там много чего

асинхронный + попытка обращения к дин.массиву как к статическому = вполне ожидаемый результат


 
arhis   (2004-02-04 14:14) [13]

Вся фигня с указателями из-за того, что мне этот стринг нафиг не нужен это мне ничего другого не придумалось, потом там будет дин массив из записи структуру которой я еще не определил, просто в ней не будет динамических элементов, поэтому я решил для начала в тупую послать массив из String[50].


 
Digitman ©   (2004-02-04 14:14) [14]


> arhis   (04.02.04 14:10) [11]
> вот это определение размера массива
> lenn - количнсвто элементов массива.
>
> MySize:=(lenn)*51;


ну неправильно это ! в корне неправильно...
неправильно именно твое предположение (основанное бог знает на чем), что твой дин.массив в памяти занимает lenn*51 байт

поэтому, чтобы не вдаваться в подробности организации дин.массивов, убирай его из программы и меняй на TStringList


 
arhis   (2004-02-04 14:19) [15]

Подскажите где. я неправильно оращаюсь к массиву.

В передатчике после всего есть вот такой простой проверочный код и он прекрасно работает:

type arrStr = array of String[50];

point : pointer;

послали буфер;

label1.Caption:=IntToStr(Socket.SendBuf(buffer^,5+MySize));

берем указатель от балды
   
    getMem(point,Mysize);
    move((Pointer(integer(buffer)+5)^),point^,MySize);
    for met:=1 to 5 do
       StringGrid1.cells[0,met]:=arrStr(point^)[met-1];


 
Verg ©   (2004-02-04 14:45) [16]

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

Ты неправильно работаешь не с массивами, ты неправильно работаешь с динамическими массивами.


> type arrStr = array of String[50];


и


> type arrStr = array[0..1] of String[50];


Есть разница?!

Динамические массивы ближе всего к дельфозным Huge String или просто String.

Видишь разницу между var S : string; и S: string[20] ?


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


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


type ArrStr = array[0..1] of string[50];
    PArrStr = ^ArrStr;
var
 Point : PArrStr;
 buffer : pointer;
begin
 Point := PArrStr(pchar(buffer)+5);// И ВСЕ!! И не надо никуда ничего мувить! И не надо никаких тут динамических массивов!!!
 for met := 0 to (MySize div sizeof(Pointer^[0])) - 1 do
  StringGrid1.cells[0,met+1] := point^[met];
 
........................
..................


 
arhis   (2004-02-04 15:14) [18]

Да какая разница мувил я это или нет. Так я проверял что посылаю и посылал то что надо, а на приеме какаято фигня.


 
arhis   (2004-02-04 15:45) [19]

Ну и как я буду резервировать место в статическом массиве под элементы, когда в одном запросе их может быть 100 а в другом 10000000000000.


 
Digitman ©   (2004-02-04 15:51) [20]


> arhis


ты по-русски понимаешь ?

тебе ясным русским языком сказали - внутренняя организация дин.массивов отличается от внутр.организации стат.массивов ! дин.массивы всегда предваряет заголовок, описывающий данные ! и его размер ненулевой ! где и как ты учитываешь это в своем коде ? нет этого !

поэтому я тебе и сказал - раз намек не пониял и не углубился в изучение внутр.структуры своего дин.массива, бросай эту затею и меняй дин.массив на TStringList, работа с ним ничуть не хуже чем дин.массив строк, зато гораздо наглядней, удобней и изящней


 
Verg ©   (2004-02-04 15:52) [21]


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


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


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

> 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];

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


 
Digitman ©   (2004-02-04 16:36) [23]


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


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


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


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


 
Verg ©   (2004-02-04 16:43) [24]


> >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;


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

> 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;


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

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

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


 
Verg ©   (2004-02-04 17:02) [27]


> 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


 
Verg ©   (2004-02-04 17:07) [28]

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


> 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


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

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


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

Для структуры типа 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);


 
Verg ©   (2004-02-04 17:30) [31]


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


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

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

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

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

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


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

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


 
Anatoly Podgoretsky ©   (2004-02-08 12:16) [33]

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


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


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


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


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


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

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


 
Verg ©   (2004-02-10 19:24) [36]


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


????


 
Polevi ©   (2004-02-10 19:39) [37]

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


 
Polevi ©   (2004-02-10 19:40) [38]

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


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

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


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


> 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] и не углубляться в устроство памяти переменных, хотя за структуру ДМ Спасибо, очень интересно.
И пожалуйста поменьше эмоций, все таки серьёзные люди.



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

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

Наверх




Память: 0.6 MB
Время: 0.026 c
7-1076687427
Samael
2004-02-13 18:50
2004.04.18
Инсталлятор без окон и дверей


14-1080238428
Yegor
2004-03-25 21:13
2004.04.18
Бесплантый интернет


1-1080633565
$tranger
2004-03-30 11:59
2004.04.18
PChar => String


3-1079872042
Vilux
2004-03-21 15:27
2004.04.18
Ado и многопоточность


14-1080209662
Dmitriy O.
2004-03-25 13:14
2004.04.18
Кто нить работал с Morfit ?