Локальные сети персональных компьютеров. Использование протоколов IPX, SPX, NETBIOS© Александр Фролов, Григорий ФроловТом 4, М.: Диалог-МИФИ, 1993, 160 стр. 2.3. Основные функции API драйвера IPXAPI драйвера протокола IPX состоит из примерно дюжины функций, предназначенных для выполнения операций с сокетами, сетевыми адресами, для приема и передачи пакетов и некоторых других операций. В этом разделе мы кратко рассмотрим состав и назначение основных функций IPX. 2.3.1. Функции для работы с сокетамиВ этом разделе мы опишем функции IPXOpenSocket и IPXCloseSocket, предназначенные для получения и освобождения сокетов. IPXOpenSocket
Перед началом передачи пакетов программа должна получить свой идентификатор - сокет. Функция IPXOpenSocket как раз и предназначена для получения сокета. Сокеты являются ограниченным ресурсом, поэтому программы должны заботиться об освобождении сокетов. Когда вы открываете (запрашиваете у IPX) сокет, вы должны указать тип сокета - короткоживущий или долгоживущий. Короткоживущие сокеты освобождаются (закрываются) автоматически после завершения программы. Долгоживущие сокеты можно закрыть только с помощью специально предназначенной для этого функции IPXCloseSocket. Такие сокеты больше всего подходят для использования резидентными программами или драйверами. Более того, для резидентных программ, работающих с IPX, вы просто обязаны использовать долгоживущие сокеты, так как в противном случае при завершении программы (и при оставлении ее резидентной в памяти) все открытые программой сокеты будут автоматически закрыты. В этом случае после активизации резидентная программа останется без сокетов. Если вы не используете динамическое распределение сокетов и задаете свой номер сокета, используйте значения в диапазоне от 4000h до 8000h или получите персональный зарегистрированный сокет у фирмы Novell. По умолчанию при загрузке оболочки рабочей станции вам доступно максимально 20 сокетов. При соответствующей настройке сетевой оболочки вы можете увеличить это значение до 150. IPXCloseSocket
Функция закрывает заданный в регистре DX сокет, короткоживущий или долгоживущий. Если с закрываемым сокетом связаны ECB, находящиеся в обработке (в состоянии ожидания завершения приема или передачи), указанные ECB освобождаются, а ожидающие завершения операции отменяются. При этом в поле InUse для таких ECB проставляется нулевое значение, а в поле CCode - значение FCh, означающее, что операция была отменена. Для отмененных ECB программы ESR не вызываются. Функцию IPXCloseSocket нельзя вызывать из программы ESR. 2.3.2. Функции для работы с сетевыми адресамиIPXGetLocalTaget
Функция применяется для вычисления значения непосредственного адреса, помещаемого в поле ImmAddress блока ECB перед передачей пакета. Так как станция-получатель может находиться в другой сети, прежде чем достигнуть цели, пакет может пройти один или несколько мостов. Поле непосредственного адреса ImmAddress блока ECB должно содержать либо адрес станции назначения (если передача происходит в пределах одной сети), либо адрес моста (если пакет предназначен для рабочей станции, расположенной в другой сети). Используя указанный в буфере размером 12 байт полный сетевой адрес, состоящий из номера сети, адреса станции в сети и сокета приложения, функция IPXGetLocalTaget вычисляет непосредственный адрес, т. е. адрес той станции в данной сети, которая получит передаваемый пакет. Формат полного адреса представлен на рис. 4.
Рис. 4. Формат полного адреса Для работы с полным адресом вы можете использовать следующую структуру: struct NET_ADDRESS { unsigned char Network[4]; unsigned char Node[6]; unsigned char Socket[2]; }; В поле Network указывается номер сети, в которой расположена станция, принимающая пакет. Поле Node должно содержать адрес станции в сети с номером, заданным содержимым поля Network. Если пакет должны принять все станции, находящиеся в сети Network, в поле Node необходимо записать адрес FFFFFFFFFFFFh. Поле Socket адресует конкретную программу, работающую на станции с заданным адресом. Если программа-сервер принимает пакеты от клиентов и возвращает клиентам свои пакеты, нет необходимости пользоваться функцией IPXGetLocalTaget для заполнения поля ImmAddress блока ECB перед отправкой ответа станции-клиенту. Когда от клиента приходит пакет, в поле ImmAddress блока ECB автоматически записывается непосредственный адрес станции (или моста), из которой пришел пакет. Поэтому для отправки ответного пакета можно воспользоваться тем же самым ECB с уже проставленным значением в поле ImmAddress. IPXGetInternetworkAddress
С помощью этой функции программа может узнать сетевой адрес станции, на которой она сама работает. Полученный адрес программа может затем использовать по своему усмотрению (например, сообщить его другой станции). Формат буфера аналогичен представленному на рис. 4, за исключением того, что в буфер не записывается сокет. Считается, что сокет программа знает, так как она его открывала. 2.3.3. Прием и передача пакетовIPXListenForPacket
Эта функция предназначена для инициирования процесса приема пакетов данных из сети. Она передает драйверу IPX подготовленный блок ECB, и тот включает его в свой внутренний список блоков ECB, ожидающих приема пакетов. Одновременно программа может подготовить несколько блоков ECB (неограниченное количество) и для каждого вызвать функцию IPXListenForPackets. Данная функция сразу возвращает управление вызвавшей ее программе, не дожидаясь прихода пакета. Определить момент приема пакета программа может либо анализируя поле InUse блока ECB, либо указав перед вызовом функции адрес программы ESR (в блоке ECB), которая получит управление сразу после прихода пакета. Если программа ESR не используется, в поле ESRAddress должно быть нулевое значение. Сразу после вызова функции IPXListenForPackets в поле InUse блока ECB устанавливается значение FEh, которое означает, что для данного блока ECB ожидается прием пакета. Как мы уже говорили, программа может ожидать одновременно много пакетов. Если программа подготовила для приема пакетов несколько блоков ECB, то для приема пришедшего пакета будет использован один из подготовленных ECB. Однако не гарантируется, что блоки ECB будут использоваться в том порядке, в котором они ставятся на ожидание приема функцией IPXListenForPackets. Если свободных, ожидающих приема пакета, блоков ECB нет, то приходящий пакет будет проигнорирован. Аналогично, если ожидается пакет по данному сокету, а сокет не открыт, пришедший пакет также будет проигнорирован. После прихода пакета в поле CCode использованного блока ECB драйвер IPX записывает код результата приема пакета, а в поле ImmAddress - непосредственный адрес станции, из которой пришел пакет. Если пакет пришел из другой сети, в этом поле будет стоять адрес моста (адрес моста в той сети, где находится принимающая станция). Затем в поле InUse блока ECB проставляется нулевое
значение и вызыва- После приема пакета в поле CCode могут находиться следующие значения:
Функция IPXListenForPackets может использоваться для приема только таких пакетов, в адресе назначения которых указан сокет, совпадающий с номером сокета, подготовленного в блоке ECB. Перед тем, как использовать сокет для приема пакетов, его необходимо открыть функцией IPXOpenSocket, описанной выше. Если запрос на прием пакета был отменен специальной функцией или в результате выполнения функции IPXCloseSoket, поле InUse блока ECB устанавливается в нулевое значение, однако программа ESR, даже если ее адрес был задан, не вызывается. В поле CCode проставляется значение FCh. IPXSendPacket
Эта функция подготавливает блок ECB и связанный с ним заголовок пакета для передачи пакета по сети. Она сразу возвращает управление вызвавшей ее программе, не дожидаясь завершения процесса передачи пакета. Определить момент завершения передачи пакета программа может либо анализируя поле InUse блока ECB, либо указав перед вызовом функции адрес программы ESR (в блоке ECB), которая получит управление сразу после завершения процесса передачи пакета. Если программа ESR не используется, в поле ESRAddress должно быть нулевое значение. Перед вызовом этой функции вам необходимо заполнить указанные выше поля в блоке ECB, подготовить заголовок пакета и, разумеется, сам передаваемый пакет. Затем вы вызываете функцию IPXSendPacket, которая ставит блок ECB в очередь на передачу. Сама передача пакета происходит асинхронно по отношению к вызывавшей ее программе. Пакет будет передан в станцию, адрес которой указан в поле ImmAddress. Если в этом поле указан адрес моста, пакет будет передан через мост в другую сеть. Разумеется, что вы должны кроме непосредственного адреса задать еще и номер сети адресата, а также адрес станции в этой сети. Для вычисления непосредственного адреса (который надо будет записать в поле ImmAddress) можно воспользоваться описанной выше функцией IPXGetLocalTaget. Сразу после вызова функции IPXSendPacket в поле InUse блока ECB устанавливается значение FFh. После завершения процесса передачи пакета поле InUse принимает значение 00h. Результат выполнения передачи пакета можно узнать, если проанализировать поле CCode блока ECB:
Обратим еще раз ваше внимание на то, что, даже если код завершения в поле CCode равен нулю, это не гарантирует успешной доставки пакета адресату. Из-за чего пакет может не дойти до адресата? Во-первых, пакет может быть потерян в процессе передачи по кабелю. Во-вторых, станция, адрес которой указан в заголовке пакета, может не работать или такой станции может вообще не быть в указанной сети. В-третьих, станция-адресат может не ожидать пакет на указанном сокете. Если в поле CCode оказалось значение FEh, это также может произойти по трем причинам. Во-первых, если пакет предназначен для другой сети, может оказаться так, что невозможно найти мост, который соединял бы эти сети. Во-вторых, если пакет предназначен для станции в той же сети, может произойти сбой в сетевом адаптере или другом сетевом оборудовании. В-третьих, пакет может быть передан станции, на которой не открыт соответствующий сокет или нет запросов на прием пакета по данному сокету. Одна из интересных особенностей при передаче пакетов заключается в том, что вы можете передавать пакеты "сами себе", т. е. передающая и принимающая программы могут работать на одной и той же станции и использовать один и тот же сокет. IPXRelinquishControl
Если ваша программа не использует ESR, она, очевидно, должна в цикле опрашивать поле InUse блока ECB, для которого выполняется ожидание завершения процесса приема или передачи пакета. Однако для правильной работы драйвера IPX в цикл ожидания необходимо вставлять вызов функции IPXRelinquishControl. Эта функция выделяет драйверу IPX процессорное время, необходимое для его правильной работы. |