Главная страница
    Top.Mail.Ru    Яндекс.Метрика
Форум: "Сети";
Текущий архив: 2004.04.18;
Скачать: [xml.tar.bz2];

Вниз

Вопрос по 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;
Скачать: [xml.tar.bz2];

Наверх




Память: 0.58 MB
Время: 0.048 c
6-1076910895
Guest
2004-02-16 08:54
2004.04.18
Сеть и пакет


14-1080293347
Igor_thief
2004-03-26 12:29
2004.04.18
ShowModal


1-1080818442
ruslan
2004-04-01 15:20
2004.04.18
меню в режиме runtime


11-1063301468
Immortal_Death
2003-09-11 21:31
2004.04.18
PStream


14-1079916395
AZ
2004-03-22 03:46
2004.04.18
Как вы делаете “бэкап” проекта при перерыве в работе?





Afrikaans Albanian Arabic Armenian Azerbaijani Basque Belarusian Bulgarian Catalan Chinese (Simplified) Chinese (Traditional) Croatian Czech Danish Dutch English Estonian Filipino Finnish French
Galician Georgian German Greek Haitian Creole Hebrew Hindi Hungarian Icelandic Indonesian Irish Italian Japanese Korean Latvian Lithuanian Macedonian Malay Maltese Norwegian
Persian Polish Portuguese Romanian Russian Serbian Slovak Slovenian Spanish Swahili Swedish Thai Turkish Ukrainian Urdu Vietnamese Welsh Yiddish Bengali Bosnian
Cebuano Esperanto Gujarati Hausa Hmong Igbo Javanese Kannada Khmer Lao Latin Maori Marathi Mongolian Nepali Punjabi Somali Tamil Telugu Yoruba
Zulu
Английский Французский Немецкий Итальянский Португальский Русский Испанский