Читаем О чём не пишут в книгах по Delphi полностью

В стандартной библиотеке сокетов (т. е. в заголовочных файлах для этой библиотеки) полагается, что адрес кодируется структурой sockaddr длиной 16 байтов, причем первые два байта этой структуры кодируют семейство протоколов, а смысл остальных зависит от этого семейства. В частности, для стека TCP/IP семейство протоколов задается константой PF_INET. (Ранее мы уже встречались с термином "семейство адресов" и константой AF_INET. В ранних версиях библиотеки сокетов семейства протоколов и семейства адресов были разными понятиями, но затем эти понятия слились в одно, и константы AF_XXX и PF_XXX стали взаимозаменяемыми). Остальные 14 байтов структуры sockaddr занимает массив типа char (напомним, что тип char в C/C++ соответствует одновременно двум типам Delphi: Char и ShortInt). В принципе, в стандартной библиотеке сокетов предполагается, что структура, задающая адрес, всегда имеет длину 16 байтов, но на всякий случай предусмотрен третий параметр функции bind, который хранит длину структуры. В сокетах Windows длина структуры может быть любой (это зависит от протокола), так что этот параметр, в принципе, может пригодиться.

Ранее уже упоминалось, что неструктурированное представление адреса в виде массива из 14 байтов бывает неудобно, и поэтому для каждого семейства протоколов предусмотрена своя структура, учитывающая особенности адреса. В частности, для протоколов стека TCP/IP используется структура sockaddr_in, размер которой также составляет 16 байтов. Из них задействовано только восемь: два для кодирования семейства протоколов, четыре для IP-адреса и два — для порта. Оставшиеся 8 байтов должны содержать нули.

Можно было бы предположить, что типы TSockAddr и TSockAddrIn, описанные в модуле WinSock, соответствуют структурам sockaddr и sockaddr_in, однако это не так. На самом деле эти типы описаны следующим образом (листинг 2.1).

Листинг 2.1. Типы TSockAddr и TSockAddrIn

SunB = packed record

 s_b1, s_b2, s_b3, s_b4: u_char;

end;

SunW = packed record

 s_w1, s_w2: u_short;

end;

in_addr = record

 case Integer of

 0: (S_un_b: SunB);

 1: (S_un_w: SunW);

 2: (S_addr: u_long);

end;

TInAddr = in_addr;

sockaddr_in = record

 case Integer of

 0: (

sin_family: u_short;

sin_port: u_short;

 sin_addr: TInAddr;

 sin_zero: array[0..7] of Char);

 1: (

sa_family: u_short;

sa_data: array[0..13] of Char);

end;

TSockAddrIn = sockaddr_in;

TSockAddr = sockaddr_in;

Таким образом, типы TSockAddr и TSockAddrIn — это синонимы типа sockaddr_in (но не того sockaddr_in, который имеется в стандартной библиотеке сокетов, а типа sockaddr_in, описанного в модуле WinSock). А тип sockaddr_in из WinSock является вариантной записью, и в случае 0 соответствует типу sockaddr_in из стандартной библиотеки сокетов, а в случае 1 — sockaddr из этой же библиотеки. Вот такая несколько запутанная ситуация, хотя на практике все выглядит не так страшно.

Примечание

Из названия типов можно сделать вывод, что тип u_short — это Word, а u_longCardinal. На самом деле u_short — это действительно Word, а вот u_long — это LongInt. Сложно сказать почему выбран знаковый тип там, где предполагается беззнаковый. Видимо, это осталось в наследство от старых версий Delphi, которые не поддерживали тип Cardinal в полном объеме. Кстати, тип u_char — это Char, а не Byte.

Перейдем, наконец, к более практически важному вопросу: какими значениями следует заполнять переменную типа TSockAddr, чтобы при передаче ее в функцию bind сокет был привязан к нужному адресу. Так как мы ограничиваемся рассмотрением протоколов TCP и UDP, нас не интересует та часть вариантной записи sockaddr_in, которая соответствует случаю 1, т. е. мы будем рассматривать только те поля этой структуры, которые имеют префикс sin.

Перейти на страницу:

Похожие книги

1С: Управление торговлей 8.2
1С: Управление торговлей 8.2

Современные торговые предприятия предлагают своим клиентам широчайший ассортимент товаров, который исчисляется тысячами и десятками тысяч наименований. Причем многие позиции могут реализовываться на разных условиях: предоплата, отсрочка платежи, скидка, наценка, объем партии, и т.д. Клиенты зачастую делятся на категории – VIP-клиент, обычный клиент, постоянный клиент, мелкооптовый клиент, и т.д. Товарные позиции могут комплектоваться и разукомплектовываться, многие товары подлежат обязательной сертификации и гигиеническим исследованиям, некондиционные позиции необходимо списывать, на складах периодически должна проводиться инвентаризация, каждая компания должна иметь свою маркетинговую политику и т.д., вообщем – современное торговое предприятие представляет живой организм, находящийся в постоянном движении.Очевидно, что вся эта кипучая деятельность требует автоматизации. Для решения этой задачи существуют специальные программные средства, и в этой книге мы познакомим вам с самым популярным продуктом, предназначенным для автоматизации деятельности торгового предприятия – «1С Управление торговлей», которое реализовано на новейшей технологической платформе версии 1С 8.2.

Алексей Анатольевич Гладкий

Финансы / Программирование, программы, базы данных