Windows Sockets Direct
Windows Sockets Direct (WSD) – это интерфейс, позволяющий в Winsock-приложениях без всякой модификации использовать преимущества сетей устройств хранения данных (System Area Networks, SAN). Высокопроизводительные SAN идеальны для самых разнообразных применений – от распределенных вычислений до трехуровневых архитектур электронной коммерции вроде показанной на рис. 13-5. B данной системе сети SAN соединяют Web-серверы (презентационный Web-уровень) с серверами бизнес-логики и с серверами базы данных, что обеспечивает высокоскоростную передачу данных между различными уровнями обработки информации. Поддержка WSD имеется в Windows 2003 и Windows 2000 Data Center Server, а также в Windows 2000 Advanced Server c Service Pack (SP) 2 и выше.SAN-соединения
Высокая производительность SAN обычно достигается за счет специализированных сетевых соединений и коммутационного оборудования. K наиболее распространенным типам SAN-соединений относятся InfiniBand, Gigabit Ethernet, FiberChannel и различные фирменные (закрытые) решения. Физическая память, разделяемая двумя компьютерами, тоже может служить SAN-соединением.Коммутационное оборудование SAN реализует немаршрутизируемый протокол, предоставляющий TCP-эквивалентные гарантии, в частности надежную доставку сообщений в правильном порядке. Эти аппаратные средства также поддерживают механизм SAN, называемый удаленным прямым доступом к памяти (Remote Direct Memory Access, RDMA); этот механизм позволяет напрямую передавать сообщения из физической памяти компьютера-источника в физическую память компьютера-получателя без промежуточной операции копирования, которая обычно выполняется на стороне, принимающей сообщения. Благодаря этому RDMA освобождает процессор и шину памяти от лишней нагрузки, связанной с операцией копирования.
Реализации SAN также позволяют обходиться без обращений к компонентам режима ядра, посылая и принимая данные напрямую между пользовательскими приложениями. Это сокращает число системных вызовов, инициируемых приложениями, и соответственно уменьшает время, затрачиваемое на выполнение системного кода поддержки сетей.
Архитектура WSD
Большинство реализаций SAN требуют модификации приложений для взаимодействия с сетевыми протоколами SAN и использования преимуществ аппаратно-реализованных протоколов и механизмов SAN вроде RDMA, но WSD позволяет любому Winsock-приложению, работающему по протоколу TCP, задействовать возможности SAN без такой модификации. Само название WSD подчеркивает, что он обеспечивает приложениям прямой доступ к оборудованию SAN, в обход стека TCP/IP. A сокращение пути передачи данных повышает производительность приложений в 2-2,5 раза.Такое сокращение достигается за счет использования программного коммутатора, размещаемого на уровень ниже Winsock DLL, как показано на рис. 13-6. Этот коммутатор переадресует сетевые операции SAN провайдеру сервисов Winsock (Winsock service provider, WSP), который предоставляется производителем SAN. WSP служит эквивалентом NDIS-драйвера, работающим в пользовательском режиме, и может проецировать аппаратные регистры SAN на память пользовательского режима, а затем манипулировать оборудованием без участия компонентов режима ядра. Однако некоторые операции все же требуют поддержки со стороны таких компонентов, например для проецирования содержимого аппаратных регистров на память пользовательского режима; эта поддержка тоже предоставляется производителем оборудования SAN. Наконец, производитель SAN предоставляет минипорт-драйвер NDIS, выступающий в роли интерфейса между стеком TCP/IP и оборудованием SAN для приложений, которые используют сетевые средства Winsock, не поддерживаемых SAN на аппаратном уровне.
Remote Procedure CaII (RPC)
RPC – стандарт сетевого программирования, разработанный в начале 80-x. Организация Open Software Foundation (теперь – The Open Group) сделала RPC частью стандарта OSF DCE (Distributed Computing Environment). Несмотря на наличие второго стандарта RPC, SunRPC, реализация RPC от Microsoft совместима со стандартом OSF DCE. RPC, опираясь на другие сетевые API (именованные каналы или Winsock), предоставляет альтернативную модель программирования, в какой-то мере скрывающую детали сетевого программирования от разработчика приложений.Функционирование RPC
Механизм RPC позволяет создавать приложения, состоящие из произвольного числа процедур, часть которых выполняется локально, а часть – на удаленных компьютерах (через сеть). RPC предоставляет модель работы с сетью, ориентированную на процедуры, а не на транспорты, что упрощает разработку распределенных приложений.Сетевое программное обеспечение традиционно базируется на модели обработки ввода-вывода. B Windows, например, сетевая операция начинается с того, что приложение выдает запрос на удаленный ввод-вывод. Операционная система обрабатывает запрос, передавая его редиректору, который действует в качестве удаленной файловой системы, обеспечивая прозрачное взаимодействие клиента с удаленной файловой системой. Редиректор передает запрос удаленной файловой системе, а после того как удаленная система выполнит запрос и вернет результаты, локальная сетевая плата генерирует прерывание. Ядро обрабатывает это прерывание, и исходная операция ввода-вывода завершается, возвращая результаты вызывающей программе.
RPC использует совершенно другой подход. Приложения RPC похожи на другие структурированные приложения: у них есть основная программа, которая для выполнения специфических задач вызывает процедуры или библиотеки процедур. Отличие приложений RPC от обычных программ в том, что некоторые библиотеки процедур в приложениях RPC выполняются на удаленных компьютерах, а некоторые – на локальном (рис. 13-7).
Для приложения RPC все процедуры кажутся локальными. Иначе говоря, вместо того чтобы заставлять программиста писать код для передачи запросов на вычисления или ввод-вывод по сети, работы с сетевыми протоколами, обработки сетевых ошибок, ожидания результатов и т. д., программное обеспечение RPC выполняет все эти задачи автоматически. Кроме того, механизм RPC в Windows работает с любыми транспортами, которые имеются в системе.
Создавая приложение RPC, программист решает, какие процедуры будут выполняться локально, а какие – удаленно. Допустим, обычная рабочая станция подключена по сети к суперкомпьютеру Cray или к специализированной машине, предназначенной для быстрого выполнения векторных вычислений. Если программист пишет программу, работающую с большими матрицами, то с точки зрения производительности имело бы смысл переложить математические вычисления на удаленный компьютер, написав программу в виде приложения RPC.
Функционирует приложение RPC следующим образом. B процессе своей работы оно вызывает как локальные процедуры, так и процедуры, отсутствующие на локальной машине. Для обработки последнего случая приложение связывается с локальной DLL, которая содержит интерфейсные процедуры (stub procedures) для всех удаленных процедур. B простой программе интерфейсные процедуры статически связываются с приложением, но в компоненте большего размера они включаются в отдельные DLL. B DCOM обычно применяется последний метод. Интерфейсная процедура имеет то же имя и тот же интерфейс, что и удаленная процедура, но вместо выполнения соответствующей операции она просто преобразует переданные ей параметры для передачи по сети – такой процесс называется маршалингом(marshaling). Маршалинг заключается в упорядочении параметров и их упаковке в определенном формате.
Далее интерфейсная процедура вызывает процедуры библиотеки RPC периода выполнения, и они находят компьютер, на котором расположены удаленные процедуры, определяют используемые этим компьютером механизмы транспорта и посылают запрос при помощи локального программного обеспечения сетевого транспорта. Когда удаленный сервер получает запрос RPC, он выполняет обратное преобразование параметров (unmarshaling), реконструирует исходный вызов процедуры и вызывает ее. Закончив обработку, сервер выполняет обратную последовательность действий для возврата результатов вызывающей программе.
Кроме интерфейса, основанного на описанном здесь синхронном вызове процедур, RPC в Windows также поддерживает асинхронный RPC(asynchronous RPC). Он позволяет приложению RPC вызывать функцию и, не дожидаясь ее выполнения, продолжать свою работу. Ha это время приложение может перейти к выполнению другого кода. Когда от сервера придет ответ, библиотека RPC периода выполнения уведомит клиент о завершении операции. При этом используется механизм уведомления, запрошенный клиентом. Если клиент выбрал для уведомления синхронизирующий объект «событие», он ждет его перехода в свободное состояние, вызвав функцию WaitForSingle-Objectили WaitForMultipleObject.Если клиент предоставляет APC (Asynchronous Procedure Call), библиотека RPC периода выполнения ставит APC в очередь потока, выполняющего RPC-функцию. Если же клиент использует в качестве механизма уведомления порт завершения ввода-вывода, он должен вызвать GetQueuedCompletionStatus,чтобы узнать об окончании работы этой функции. Наконец, клиент может опрашивать библиотеку RPC периода выполнения о ходе выполнения операции, вызывая RcpAsyncGetCallStatus.
Помимо библиотеки периода выполнения в Microsoft RPC входит компилятор MIDL (Microsoft Interface Definition Language). Этот компилятор упрощает создание приложений RPC Программист пишет набор обычных прототипов функций (предполагается, что он использует язык C или C++), описывающих удаленные процедуры, а затем помещает их в какой-либо файл. Далее он добавляет к этим прототипам нужную дополнительную информацию, например уникальный для сети идентификатор пакета процедур, номер версии и атрибуты, указывающие, являются ли параметры входными, выходными или и теми, и другими одновременно. B конечном счете программист получает файл на языке IDL (Interface Definition Language).
Подготовленный IDL-файл транслируется компилятором MIDL, который создает интерфейсные процедуры для клиентской и серверной сторон, а также заголовочные файлы, включаемые в приложение. Когда клиентское приложение связывается с файлом интерфейсных процедур, компоновщик разрешает все ссылки на удаленные процедуры. Аналогичным образом удаленные процедуры устанавливаются на серверной машине. Программист, который намерен вызывать существующее приложение RPC, должен написать только клиентскую часть программы и скомпоновать ее с локальной библиотекой RPC периода выполнения.
Библиотека RPC периода выполнения использует для взаимодействия с транспортным протоколом универсальный интерфейс провайдеров трансnopmaRPC(RPC transport provider interface). Этот интерфейс служит тонкой прослойкой между механизмом RPC и транспортом, которая увязывает операции RPC с функциями, предоставляемыми транспортом. RPC в Windows реализует DLL-модули провайдеров транспорта для именованных каналов, NetBIOS, SPX, TPC/IP и UDP. B Windows Server 2003 провайдер транспорта NetBIOS изъят, но добавлен провайдер для HTTR Аналогичным образом RPC поддерживает работу с различными средствами сетевой защиты.
ПРИМЕЧАНИЕ B Windows 2000 можно написать новые DLL-модули провайдеров для поддержки дополнительных транспортов, но, начиная с Windows XP, встраивание дополнительных DLL провайдеров не поддерживается.
Большинство сетевых служб Windows является приложениями RPC, а это значит, что они могут вызываться как локальными процессами, так и процессами на удаленных машинах. Таким образом, удаленный клиентский компьютер может обращаться к службам сервера для просмотра списка общих ресурсов, открытия файлов, записи данных в очереди печати или добавления пользователей на этом сервере, либо он может вызывать Messenger Service (Службу сообщений) для посылки сообщений (конечно, при наличии соответствующих прав доступа).
Сервер может регистрировать свое имя по адресу, который будет доступен клиенту при поиске. Эта возможность, называемая публикацией имени сервера,реализована в RPC и интегрирована с Active Directory. Если Active Directory не установлена, служба локатора имен возвращается к широковещательной рассылке с использованием NetBIOS. Это позволяет взаимодействовать с системами под управлением Windows NT 4 и дает возможность RPC функционировать на автономных серверах и рабочих станциях.
Защита в RPC
RPC интегрирован с компонентами поддержки защиты (security support providers, SSP), что позволяет клиентам и серверам RPC использовать аутентификацию и шифрование при коммуникационной связи. Когда серверу RPC требуется защищенное соединение, он сообщает библиотеке RPC периода выполнения, какую службу аутентификации следует добавить в список доступных служб аутентификации. A когда клиенту нужно использовать защищенное соединение, он выполняет привязку к серверу. Bo время привязки к серверу клиент должен указать библиотеке RPC службу аутентификации и нужный уровень аутентификации.Различные уровни аутентификации обеспечивают подключение к серверу только авторизованных клиентов, проверку каждого сообщения, получаемого сервером (на предмет того, послано ли оно авторизованным клиентом), контроль за целостностью RPC-сообщений и даже шифрование данных RPC-сообщений. Чем выше уровень аутентификации, тем больше требуется обработки. Клиент также может указывать имя участника безопасности(principal name) для сервера. Участник безопасности(principal) – это сущность, распознаваемая системой защиты RPC Сервер должен зарегистрироваться в SSP под именем участника безопасности, специфичным для SSP.SSP берет на себя все, что связано с аутентификацией и шифрованием при коммуникационной связи, не только для RPC, но и для Winsock. B Windows несколько встроенных SSP, в том числе Kerberos SSP, реализующий аутентификацию Kerberos v5, SChannel (Secure Channel), реализующий Secure Sockets Layer (SSL), и протоколы TLS (Transport Layer Security). Если SSP не указан, программное обеспечение RPC использует встроенные средства защиты нижележащего транспорта. Одни транспорты, в частности именованные каналы и локальный RPC, имеют такие средства защиты, а другие, например TCP, – нет. B последнем случае RPC при отсутствии указанного SSP выдает небезопасные вызовы.
Еще одна функция защиты RPC позволяет серверу подменять клиент через функцию RpcImpersonateClient.Когда сервер заканчивает выполнение операций, потребовавших подмены клиента собой, он возвращается к использованию своих идентификационных данных защиты вызовом функции RpcRevertToSelfили RpcRevertToSelJEx(подробнее о подмене, или олицетворении, см. главу 8).
Реализация RPC
Реализация RPC изображена на рис. 13-8, где показано, что приложение на основе RPC связано с библиотекой RPC периода выполнения (\Windows\Sys- tem32\Rpcrt4.dll). Последняя предоставляет для интерфейсных RPC-функций приложений функции маршалинга, а также функции для приема и передачи упакованных данных. Библиотека RPC периода выполнения включает процедуры поддержки RPC-взаимодействия через сеть и разновидность RPC под названием локальный RPC.Локальный RPC позволяет двум процессам взаимодействовать в одной системе, при этом библиотека RPC в качестве сетевого API использует LPC в режиме ядра (об LPC см. главу 3). Когда RPC-взаимодей-ствие осуществляется между удаленными системами, библиотека RPC использует API-функции Winsock, именованного канала или Message Queuing.ПРИМЕЧАНИЕ Message Queuing в Windows Server 2003 не поддерживается в качестве транспорта.
Подсистема RPC (RPCvSS) ( \Windows\System32\Rpcss.dll) реализована в виде Windows-сервиса. RPCSS сама является приложением RPC, которое взаимодействует со своими экземплярами на других системах для поиска имен, регистрации и динамического подключения конечной точки (dynamic end-point mapping). (Для упрощения на рис. 13-8 не показана связь RPCSS с библиотекой RPC периода выполнения.)
API-интерфейсы доступа к Web
Чтобы упростить разработку Интернет-приложений, в Windows предусмотрены клиентские и серверные API-интерфейсы доступа к Интернету. C помощью этих API приложения могут предоставлять и использовать сервисы Gopher, FTP и HTTP, не зная внутреннего устройства соответствующих протоколов. Клиентские API включают Windows Internet, также называемый WinInet (позволяет приложениям взаимодействовать с протоколами Gopher, FTP и HTTP), и WinHTTP (дает возможность приложениям взаимодействовать с протоколом HTTP). B определенных ситуациях WinHTTP удобнее WinInet. HTTP – это серверный API, введенный в Windows Server 2003 для поддержки разработки серверных Web-приложений.WinInet
WinInet поддерживает протоколы Gopher, FTP и HTTP версий 1.0 и 1.1. Этот API делится на наборы под-API, специфичные для каждого протокола. Используя API-функции FTP вроде InternetConnectдля подключения к FTP-cep-веру, FtpFindFirstFileи FtpFindNextFileдля перечисления содержимого FTP-каталога, а также FtpGetFileи FtpPutFileдля приема и передачи файлов, разработчик приложения может не задумываться о деталях, связанных с установлением соединения и форматированием TCP/IP-сообщений для протокола FTP API-функции Gopher и HTTP обеспечивают аналогичный уровень абстракции. WinInet применяется базовыми компонентами Windows, например Windows Explorer и Internet Explorer.WinHTTP
Текущая версия WinHTTP API – 5.1; она доступна в Windows 2000 с Service Pack 3, в Windows XP и Windows Server 2003- Этот API обеспечивает абстракцию протокола HTTP 1.1 для клиентских HTTP-приложений по аналогии с HTTP API в WinInet. Однако, если WinInet HTTP API предназначен для интерактивных клиентских приложений, то WinHTTP API – для серверных приложений, взаимодействующих с HTTP-серверами. Серверные приложения часто реализуются как Windows-службы без UI, поэтому им не нужны диалоговые окна, которые позволяют выводить API-функции WinInet. Кроме того, WinHTTP API лучше масштабируется и предоставляет средства защиты вроде подмены потоков, недоступные в WinInet API.
HTTP
C помощью HTTP API, реализованного в Windows Server 2003, серверные приложения могут регистрироваться на прием HTTP-запросов с определенных URL, принимать такие запросы и передавать HTTP-ответы. HTTP API включает поддержку SSL (Secure Sockets Layer), чтобы приложения могли обмениваться данными по защищенным HTTP-соединениям. Этот API поддерживает кэширование на серверной стороне, модели синхронного и асинхронного ввода-вывода, а также адресацию по IPv4 и IPv6. HTTP API используется IIS версии 6 (поставляется с Windows Server 2003).HTTP API, к которому приложения обращаются через библиотеку Httpapi.dll, опирается на драйвер Http.sys режима ядра. Http.sys запускается по требованию при первом вызове HttpInitializeлюбым приложением. Функция HttpCreateHttpHandleпозволяет создавать закрытую очередь запросов, а функция HttpAddUrl– указывать URL-адреса, по которым приложение собирается принимать запросы для обработки. Используя очереди запросов и их зарегистрированные URL, Http.sys дает возможность обслуживать НТТР-запросы на одном порту, например 80, более чем одному приложению.
HttpReceiveHttpRequestпринимает входящие запросы, направленные по зарегистрированным URL, zHttpSendHttpRespomeпередает HTTP-ответы. Обе функции работают в асинхронном режиме, так что приложение может определять, закончена ли какая-то операция, используя GetOverlappedResultили порты завершения ввода-вывода.
Приложения могут использовать Http.sys для кэширования данных в неподкачиваемой физической памяти, вызывая HttpAddToFragmentCacheи сопоставляя имя фрагмента с кэшируемыми данными. Ддя выделения неспроецированных страниц физической памяти Http.sys запускает функцию MmAllocate-PagesForMdl,принадлежащую диспетчеру памяти. Когда Http.sys требуется сопоставление виртуального адреса с физической памятью, описываемой элементом кэша (например, если Http.sys копирует данные в кэш или передает их из кэша), он вызывает MmMapLockedPagesSpecifyCache,а по окончании операций – MmUnmapLockedPages.Http.sys хранит кэшируемые данные до тех пор, пока приложение не объявит их недействительными или пока не истечет срок их актуальности, заданный приложением. Http.sys также усекает кэшируемые данные при пробуждении рабочего потока из-за перехода в свободное состояние события, уведомляющего о малом объеме памяти (информацию об этом событии см. в главе 7). Если при вызове HttpSendHttpResponseприложение указывает одно или несколько имен фрагментов, Http.sys передает указатель на данные, кэшируемые в физической памяти, драйверу TCP/ IP и тем самым исключает лишнюю операцию копирования.
Именованные каналы и почтовые ящики
Именованные каналы и почтовые ящики – это API, изначально разработанные Microsoft для OS/2 LAN Manager и впоследствии перенесенные в Windows NT Именованные каналы обеспечивают надежную двустороннюю связь, тогда как почтовые ящики – ненадежную одностороннюю передачу данных. Преимущество почтовых ящиков – в поддержке широковещательной передачи. Оба API используют систему защиты Windows, что позволяет серверам контролировать, какие клиенты могут подключаться к ним.Серверы назначают именованным каналами и их клиентам имена в соответствии с универсальными правилами именования (Universal Naming Convention, UNC), которые обеспечивают независимый от протоколов способ идентификации ресурсов в Windows-сетях. O реализации UNC-имен мы расскажем позже.
Функционирование именованных каналов
Коммуникационная связь по именованному каналу включает сервер именованного канала и клиент именованного канала. Сервером именованного канала является приложение, создающее именованный канал, к которому подключаются клиенты. Формат имени канала выглядит так: \\Cepвep\Pipe\ ИмяКанала. Элемент Серверуказывает компьютер, на котором работает сервер именованного канала. Элемент Pipeдолжен быть строкой «Pipe», а Имя-Канала –уникальное имя, назначенное именованному каналу. Уникальная часть имени канала может включать подкаталоги. Пример такого UNC-име-ни канала – \\MyComputer\Pipe\MyServerApp\ConnectionPipe.Для создания именованного канала сервер использует Windows-функцию CreateNamedPipe.Одним из входных параметров этой функции является указатель на имя канала в форме \\.\Рiре\ИмяКанала, где «\\.\» – псевдоним локального компьютера, определенный в Windows. Функция также принимает необязательный дескриптор защиты, запрещающий несанкционированный доступ к именованному каналу, флаг, указывающий, должен ли канал быть двусторонним или односторонним, параметр, определяющий максимальное число одновременных соединений по данному каналу, и флаг режима работы канала (побайтовой передачи или передачи сообщений).
Большинство сетевых API-функций работают только в режиме побайтовой передачи. Это означает, что переданное сообщение может быть принято адресатом в виде нескольких фрагментов, из которых воссоздается полное сообщение. Именованные каналы, работающие в режиме передачи сообщений, упрощают реализацию приемника, поскольку в этом случае число передач и приемов одинаково, а приемник, разом получая целое сообщение, не должен заботиться об отслеживании фрагментов сообщений.
При первом вызове CreateNamedPipeс указанием какого-либо имени создается первый экземпляр именованного канала с этим именем и задается поведение всех последующих экземпляров этого канала. Повторно вызывая CreateNamedPipe,сервер может создавать дополнительные экземпляры именованного канала, максимальное число которых указывается при первом вызове CreateNamedPipe.Создав минимум один экземпляр именованного канала, сервер выполняет Windows-функцию ConnectNamedPipe,после чего именованный канал позволяет устанавливать соединения с клиентами. Функция ConnectNamedPipeможет выполняться как синхронно, так и асинхронно, и она не завершится, пока клиент не установит соединение через данный экземпляр именованного канала (или не возникнет ошибка).
Для подключения к серверу клиенты именованного канала используют Windows-функцию CreateFileили CallNamedPipe,указывая при вызове имя созданного сервером канала. Если сервер вызывает функцию ConnectNamedPipe,профиль защиты клиента и запрошенные им права доступа к каналу (для чтения или записи) сравниваются с дескриптором защиты канала (подробнее об алгоритмах проверки прав доступа см. главу 8). Если клиенту разрешен доступ к именованному каналу, он получает описатель, представляющий клиентскую сторону именованного канала, и функция ConnectNamedPipe,вызванная сервером, завершается.
После того как соединение по именованному каналу установлено, клиент и сервер могут использовать его для чтения и записи данных через Windows-функции ReadFileи WriteFile.Именованные каналы поддерживают как синхронную, так и асинхронную передачу сообщений. Взаимодействие клиента и сервера через именованный канал показано на рис. 13-9.
Уникальная особенность API именованного канала заключается в том, что он позволяет серверу олицетворять клиент с помощью функции ImpersonateNamedPipeClient.O том, как используется олицетворение в клиент-серверных приложениях, см. раздел «Олицетворение» главы 8.
Функционирование почтового ящика
Почтовые ящики предоставляют механизм ненадежного одностороннего широковещания. Одним из примеров приложений, использующих этот тип коммуникационной связи, является сервис синхронизации времени, который каждые несколько секунд широковещательно рассылает в пределах домена сообщение с эталонным временем. Такие сообщения не критичны для работы компьютеров в сети, поэтому они рассылаются через почтовые ящики.Как и именованные каналы, почтовые ящики интегрированы с Windows API. Сервер почтового ящика создает почтовый ящик вызовом CreateMailslot.Входным параметром этой функции является имя в форме «\\.\Mailslot\ИмяПочтовогоЯщика». Сервер может создавать почтовые ящики только на той машине, на которой он работает, а назначаемые им имена почтовых ящиков могут включать подкаталоги.