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