Форум: "WinAPI";
Текущий архив: 2002.06.13;
Скачать: [xml.tar.bz2];
ВнизНарод! Ну что такое буфер, а? Найти похожие ветки
← →
chernoruk (2002-04-09 19:08) [0]Скажите хоть кто-нибудь, как понимать буфер, который надо указывать среди параметров Send и RecV?
← →
ION T (2002-04-09 19:18) [1]Send и Recv чего?
← →
MBo (2002-04-09 19:21) [2]PChar, наверно
← →
Anatoly Podgoretsky (2002-04-09 19:28) [3]Buffer это обычно массив
← →
Digitman (2002-04-10 08:35) [4]>chernoruk
Буфером, как правило, именуют непрерывный блок памяти, распределенный программой тем или иным (не важно каким) образом для временного хранения неких данных, требующих отложенной (распределенной во времени) программной обработки.
Буфер однозначно определяется двумя параметрами : адресом его начала в памяти (указателем на адрес первого байта) и полным размером (обычно - в байтах). Иногда также оперируют понятием "смещение в буфере", т.е. адресом некоего текущего байта (в общем случае - элемента, могущего состоять из более чем одного байта) в этом блоке, расчитанного относительно адреса начала буфера (первого байта в нем).
Касаемо вызовов WinsockAPI send() и recv() буфер, требуемый в качестве одного из параметров, м.б. организован любым доступным и удобным в конкретном контексте способом, например :
var
dynamic_buf: PInteger;
static_buf: Integer;
..
New(dynamic_buf);
send(..., dynamic_buf ^, SizeOf(dynamic_buf ^), ...);
send(..., static_buf, SizeOf(static_buf^), ...);
← →
Digitman (2002-04-10 08:38) [5]SizeOf(static_buf) - правильней будет)
← →
Raptor (2002-04-10 16:48) [6]2 Digitman
Этим способом можно получить буфер размером только 4 байта (Д4, Д5, Д6). Ведь тип Integer в Д4, Д5, Д6 соодержит только 4 байта.
Имхо, правильней сделать так:
var
buf:Pointer;
ptr:PByteArray;
b:Byte;
...
GetMem(buf,<здесь размер буфера в байтах>);
...
send(..., buf,<здесь размер буфера в байтах>, ...);
recv(..., buf,<здесь размер буфера в байтах>, ...);
...
FreeMem(buf,<здесь размер буфера в байтах>);
...
Обращаться к элементам в буфере можно например так:
ptr:=buf;
b:=Ptr(123);
Ptr(12):=128;
Ptr(34):=Ord("A");
и т.д.
← →
Digitman (2002-04-10 17:06) [7]>Raptor
1. Я же привел только пример, частный случай ! В общем же случае абсолютно безразлично : буфер, эквив-ный по размеру переменной типа Integer там будет или еще чего-нибудь. Важно, чтобы автор уяснил для себя, что есть "буфер" как таковой - в этом суть его вопроса.
2. Пример же, приведенный тобой, увы, работать не будет - в run-time он возбудит исключение по AV. Убедись сам в этом и не путай, пожалуйста, автора вопроса.
← →
chernoruk (2002-04-10 20:45) [8]Сейчас переварю....
← →
Raptor (2002-04-11 16:21) [9]2 Digitman
Пример же, приведенный тобой, увы, работать не будет - в run-time он возбудит исключение по AV. Убедись сам в этом и не путай, пожалуйста, автора вопроса.
Я никого не путаю. Никакого AV в run-time не будет. Убедись в этом сначала сам, а уж потом делай такие замечания.
Правда я писал на ходу потому сделал небольшую ошибку. Ведь Ptr это указатель на массив. Пэтому надо писать не Ptr(12):=128, а Ptr[12]:=128 и т.д. Но эта ошибка выплывает еще на этапе компиляции, а не в рантайме. По видимому ты мой код даже не компилировал (иначе заметил бы эту ошибку), а уже делаешь свои глубокомысленные выводы.
← →
Digitman (2002-04-11 17:00) [10]>Raptor
А его и компилировать не нужно - и так видно, что он неверен.
Тебе аргументы нужны ? Изволь.
1. Открывай модуль Winsock, находи декларацию ф-ции send().
Вот она :
function send(s: TSocket; var Buf; len, flags: Integer): Integer; stdcall;
Видишь жирное " var" ? Что это означает ? А означает это только одно - передача фактического параметра как нетипизированного параметра по ссылке.
Как поступит компилятор по-умолчанию, если ты передашь в send() в кач-ве факт.параметра некую переменную любого простого базового типа ? Поступит он просто - передаст адрес этой переменной. А тебе что нужно передать в ф-цию, если твоя переменная - это указатель на местоположение в памяти динамически распределенного буфера ? ЗНАЧЕНИЕ ПЕРЕМЕННОЙ- УКАЗАТЕЛЯ, а не ее адрес !!!!!!! Ты же фактически передаешь ИМЕННО адрес переменной, поэтому за буфер ф-цией send() будет принято совсем не то, что ты ожидаешь - буфером станет САМА ПЕРЕМЕННАЯ-УКАЗАТЕЛЬ, а не та область памяти, на которую ссылается ее содержимое. И это - грубая ошибка, которая в подавляющем большинстве случаев приводит к АV.
Так вот чтобы компилятор не действовал по-умолчанию, ты и должен РАЗЫМЕНОВАТЬ свою переменную-указатель, тем самым как бы перекрывая автоматические действия компилятора в таком случае.
На то и есть та самая "галка" (унарный оператор разыменования), что стоит в моем примере для случая сdynamic_buf: PInteger
. У тебя же - ситуация аналогичная, ты передаешь параметром переменную указ.типаbuf: Pointer
, однако разыменование ты сделать и не подумал.
Зато начал про ошибки компиляции говорить, которые никакого отношения к моей контрреплике не имеют - я говорил об AV в run-time и только.
← →
Raptor (2002-04-11 23:23) [11]2 Digitman
Да, ты прав, в даном конкретном случае разыменование надо было сделать. Но это детали и особенности реализации передачи буфера для каждой отдельно взятой функции. Я же писал о буферах вообще, а не только применительно к функции send. Поэтому не смотрел в описание этой функции var там параметр или нет. А твоим примером буфера практически невозможно воспользоваться человеку, котрый в этом мало понимает и каковым, судя по всему, является автор вопроса. Потому как, допустим, ему сначала надо передать 100 байт, а потом 153 байта, а потом еще какое-то наперед неизвестное количество. Как ему воспользоваться твоим примером? Как с помощью этого примера создать буфер требуемого размера? Как с ним обращаться? Потому я и привел свой вариант, который, с моей точки зрения, более детально описывает сам процесс работы с буфером.
Страницы: 1 вся ветка
Форум: "WinAPI";
Текущий архив: 2002.06.13;
Скачать: [xml.tar.bz2];
Память: 0.48 MB
Время: 0.005 c