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

Параметр struct указывает тип сокета и может принимать одно из двух значений: SOCK_STREAM (для потоковых протоколов) и SOCK_DGRAM (для дейтаграммных протоколов).

Параметр protocol позволяет указать, какой именно протокол будет использоваться сокетом. Этот параметр можно оставить равным нулю — тогда будет выбран протокол по умолчанию, отвечающий условиям, заданным первыми двумя параметрами. Для стека TCP/IP потоковый протокол по умолчанию — TCP, дейтаграммный — UDP. В некоторых примерах можно увидеть значение третьего параметра равно IPPROTO_IP. Значение этой константы равно 0, и ее использование только повышает читабельность кода, но приводит к тому же результату: будет выбран протокол по умолчанию. Если требуется протокол, отличный от протокола по умолчанию (например, в некоторых реализациях стека TCP/IP существует протокол RDP — Reliable Datagram Protocol, надежный дейтаграммный протокол), следует указать здесь соответствующую константу (для RDP это будет IPPROTO_RDP). Можно также явно задать TCP или UDP с помощью констант IPPROTO_TCP и IPPROTO_UDP соответственно.

Тип TSocket предназначен для хранения дескриптора сокета. Формально он совпадает с 32-битным беззнаковым целым типом, но об этом лучше не вспоминать, т. к. любые операции над значениями типа TSocket бессмысленны. Значение, возвращаемое функцией socket, следует сохранить в переменной соответствующего типа и затем использовать для идентификации сокета при вызове других функций. Если по каким-то причинам создание сокета невозможно, функция вернет значение INVALID_SOCKET. Причину ошибки можно узнать с помощью функции WSAGetLastError.

Сокет, созданный с помощью функции socket, не привязан ни к какому адресу. Привязка осуществляется с помощью функции bind, имеющей следующий прототип:

function bind(s: TSocket; var addr: TSockAddr; namelen: Integer): Integer;

Первый параметр этой функции — дескриптор сокета. который привязывается к адресу. Здесь, как и в остальных подобных случаях, требуется передать значение, которое вернула функция socket. Второй параметр содержит адрес, к которому требуется привязать сокет, а третий — длину структуры, содержащей адрес.

Функция bind предназначена для сокетов, реализующих разные протоколы из разных стеков, поэтому кодирование адреса в ней сделано достаточно универсальным. Впрочем, следует отметить, что разработчики модуля WinSock для Delphi выбрали не лучший способ перевода прототипа этой функции на Паскаль, поэтому универсальность в значительной мере утрачена. В оригинале прототип функции bind имеет следующий вид:

int bind(SOCKET s, const struct sockaddr FAR* name, int namelen);

Видно, что второй параметр — это указатель на структуру sockaddr. Однако C/C++ позволяет при вызове функции в качестве параметра передать указатель на любую другую структуру, если будет выполнено явное приведение типов. Для каждого семейства адресов предусмотрена своя структура, и в качестве фактического параметра передастся указатель на эту структурy. Если бы авторы модуля WinSock описали второй параметр как параметр-значение типа указатель, можно было бы поступать точно так же. Однако они описали этот параметр как параметр-переменную. В результате на двоичном уровне ничего не изменилось: и там, и там в стек помещается указатель. Однако компилятор при вызове функции bind не допустит использования никакой другой структуры, кроме TSockAddr, а эта структура не универсальна и удобна, по сути дела, только при использовании стека TCP/IP. В других случаях наилучшим решением будет самостоятельно импортировать функцию bind из wsock32.dll с нужным прототипом. При этом придется импортировать и некоторые другие функции, работающие с адресами. Впрочем мы здесь ограничиваемся только протоколами TCP и UDP, поэтому больше останавливаться на этом вопросе не будем.

Примечание

На самом деле существует способ передать в функцию bind с таким прототипом параметр addr любого типа, совместимого с этой функцией. Если A — некая переменная типа, отличающегося от TSockAddr, то передать в качестве параметра-переменной ее можно так: PSockAddr(@А)^. Однако подобные низкоуровневые операции программу не украшают.

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

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

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

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

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

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