- •5. Управление коммуникациями в ос
- •5.1. Общая характеристика коммуникаций
- •5.2. Концепции технологии Клиент-Сервер
- •5.3. Внутренние коммуникации между процессами
- •5.3.1. Неименованные каналы
- •5.3.2. Обмен сообщениями
- •5.3.3. Обмен данными через Clipboard
- •1. Подготовка данных для передачи в Clipboard;
- •2. Проверка наличия требуемого формата данных в Clipboard
- •3. Чтение данных из Clipboard
- •4. Закрытие Clipboard
- •1. Открытие Clipboard
- •5.3.4. Обмен данными по технологии dde
- •5.3.5. Обмен данными по технологии ole
- •5.3.5.1. Введение
- •5.3.5.2. Понятие документ-ориентированной среды
- •5.3.5.3. Принципы ole
- •5.3.5.4. Характеристика технологии ole
- •5.3.5.4.1. Ole реализует концепцию визуального редактирования - редактирования на месте.
- •5.3.5.4.2. Другой особенностью ole является возможность приложения предоставить ряд своих функций (например, проверку орфографии) для доступа из других приложений - ole-Automation.
- •5.3.5.4.3. Ядром ole стал способ хранения данных в составном документе.
- •5.3.5.4.4. Дополнительные возможности ole:
- •5.3.5.4.5. Иерархия средств ole
- •5.3.5.4.6. Недостатки ole
- •5.3.5.4.7. Трехуровневая адресация ole-объекта
- •5.4. Внешние коммуникации
- •5.4.1. Протоколы тср/ip
- •5.4.1.1. Определение и достоинства протокола tcp/ip
- •5.4.1.2. Архитектура tcp/ip
- •5.4.1.3. Соответствие между моделями tcp/ip и iso osi
- •5.4.2. Протокол ip
- •5.4.2.1. Структура заголовка ip-пакета
- •5.4.3. Протокол udp
- •5.4.4. Протокол tcp
- •5.4.4.1. Структура tcp-сегмента
- •5.4.4.2. Этапы tcp-сеанса
- •5.4.5. Программные средства поддержки сетей
- •5.4.5.1. Состав программных средств поддержки сетей
- •1. Почтовые ящики
- •2. Именованные каналы
- •3. Удаленные вызовы процедур
- •4. Протокол NetBios
- •5.4.5.2. Программные средства работы с сокетами
- •5.4.6. Сетевое программное обеспечение уровня приложений
- •5.4.6.1. Протокол ftp
- •5.4.6.2. Протокол smtp
5.2. Концепции технологии Клиент-Сервер
Вопрос (
Технология клиент/сервер - это распределение прикладной программы по двум логически различным компонентам, каждый из которых выполняет свои отдельные функции.
)Вопрос
Вопрос (
Обычно клиент дает запросы на сервер на выполнение от своего имени определенной работы.
)Вопрос
Вопрос (
Задачей сервера является обработка запросов и возврат результатов клиенту.
)Вопрос
З а п р о с ы
|- - > - > - > - | > - > - > - > ----------|
^ | v
---|------ | -----|----
| Клиент | | | Сервер |
---|----- | -----|----
^ | v
|-- - < - < - < - | < - < - < - < ----------|
О т в е т ы
Этот процесс чаще всего происходит на физически разделенных компьютерах через тот или иной тип сети. Хотя это и не обязательно.
Чтобы приложение стало действительно приложением клиент/сервер, необходима соответствующая архитектура. Логика приложения должна быть разделена на отдельные компоненты - запрашивающий компонент, который дает запросы и ожидает возврата от отвечающего компонента - сервера.
Такое логическое разделение позволяет лучше подготовить приложение к распределению в сети.
Независимость компонентов приложения - обязательное требование архитектуры клиент/сервер.
Какие из компонентов приложения лучше рассматривать как клиентские, а какие - как серверные, является вопросом проектирования. Можно дать лишь следующие общие рекомендации:
Вопрос (
Клиент: ввод/вывод информации; взаимодействие с пользователем; формулировка запросов; логика приложения.
)Вопрос
Вопрос (
Сервер: запросы к совместно используемым ресурсам; обработка транзакций.
)Вопрос
Правильное распределение кода по клиентскому и серверному компонентам является ключевым вопросом в проектировании системы.
Взаимодействие между серверными и клиентскими компонентами приложения может быть декомпозировано на приведенные выше 7 уровней. И на каждом из уровней, особенно начиная с 3-го, можно выделять клиентский и серверный компоненты.
Существует множество методов взаимодействия между клиентскими и серверными компонентами: Выбор метода определяется тем, к какому из двух видов относится взаимодействие: к внутреннему или внешнему.
5.3. Внутренние коммуникации между процессами
5.3.1. Неименованные каналы
Как следует из всего предыдущего материала, современные операционные системы являются многозадачными.
Суть многозадачности состоит в возможности одновременного (параллельного) выполнения нескольких программ. При этом понятие одновременности носит несколько условный характер.
Если процессоров много, то программы действительно могут выполняться параллельно. Но, если процессор один (а так бывает очень часто), то говорят о псевдопараллельном выполнении программ.
В этом случае важную роль начинает играть такое устройство компьютера, как таймер. По сигналам от таймера происходит переключение с выполнения одной программы на выполнение другой программы. При очень быстрых переключениях они становятся незаметными и создается иллюзия подлинной параллельности - псевдопараллельность.
Однако параллельное (или псевдопараллельность) выполнение программ – это всего лишь один из уровней параллельности (более высокий).
Существует и более низкий уровень параллельности, когда в рамках одной программы одновременно выполняются несколько процедур.
В этом случае говорят не о многозадачности, а о многопоточности, т. е. выполнение каждой процедуры представляет собой поток.
В статике это выглядит следующим образом.
Создается программы, в которой имеется некоторое количество процедур, и с помощью дополнительных примитивов, а такие есть в любой современной ОС, эти процедуры запускаются на параллельное выполнение.
В этом многопоточном случае таймер также выполняет функцию переключения, а именно, какое-то время выполняется одна процедура, потом следующая и т.д.
Если с одновременным выполнением программ более менее ясно, зачем они нужны, то не совсем может быть ясно, зачем нужны программы с одновременным выполнением процедур.
Такие программы широко используются в том случае, если они взаимодействуют с внешней средой.
Представим себе, что написана программа расчетов по каким-нибудь формулам, т. е. программа, не взаимодействующая с внешней средой. Она запущена на выполнение и работает. В целом время ее работы, конечно, важно, но оно может в разное время быть разным. Например, при первом запуске в системе выполнялось 3 программы, а во втором – 10. Ясно, что при втором запуске программа будет работать дольше. Но это и не очень страшно, подсчитает свои формулы не за 5, например, а за 10 сек.
Совершенно иная ситуация имеет место, если, например, программа принимает информацию из линии связи. Импульс, соответствующий какому-нибудь очередному биту, появляется в определенный момент времени, не раньше и не позже. Если в момент появления импульса программа будет заниматься не считыванием этого импульса из нужного регистра сдвига, а, например, декодированием ранее принятых байтов, то она может пропустить прием соответствующего бита.
Для реализации подобного типа систем и нужны многопоточные программы.
В данном конкретном примере программа может содержать два потока, один из которых, имея очень высокий приоритет, вовремя будет считывать биты из канала связи, а другой поток будет не торопясь собирать эти биты в байты, байты в кодовые комбинации, а затем декодировать сообщение.
Структура такой многопоточной программы выглядит следующим образом:
void proc1() { //поток, читающий данные из канала строго в заданные
//моменты времени
while (true) {
...
}
}
void proc2() { //поток, обрабатывающий данные, полученные первым потоком
while (true) {
...
}
}
void main() {
CreateThread(..., proc1, ...);//параметров у этой функции много, proc1 -
CreateThread(..., proc2, ...);// это только один из параметров
while (клавиша не нажата) {
}
}
Потоки proc1() и proc2() должны взаимодействовать через общие структуры данных. Вот такой общей структурой данных для них и является “канал”.
Канал – это участок разделяемой памяти, который процессы могут использовать для взаимодействия. Процесс, который создает канал, является процессом – сервером. Процесс, который соединяется с каналом, является процессом – клиентом. Один процесс пишет информацию в канал, другой процесс читает из канала.
Вопрос (
Каналы могут быть двух типов:
неименованные каналы;
именованные каналы.
)Вопрос
Вопрос (
Неименованные каналы требуют меньше ресурсов, но обладают меньшими возможностями. Неименованные каналы могут быть использованы для взаимодействия между потоками одного приложения.
Именованные каналы могут использоваться для взаимодействия между приложениями, в том числе выполняющимися на разных физических машинах. Поэтому именованные каналы будут рассмотрены позже.
)Вопрос
Вопрос (
Неименованный канал создается вызовом:
CreatePipe(&hReadPipe, &hWritePipe, NULL, 0);
Вызов возвращает две ссылки, одна из которых используется для чтения, а другая для записи.
Там, где передан 0, указывается размер канала. При значении 0 система устанавливает размер по умолчанию.
)Вопрос
Вопрос (
Чтение производится вызовом:
ReadFile(hReadPipe, &NewByte, 1, &NumberOfBytesRead, NULL);
)Вопрос
Вопрос (
Запись производится вызовом:
WriteFile(hWritePipe, Buffer, nBytes,&NumberOfBytesWritten, NULL);
)Вопрос
Вопрос (
Канал закрывается вызовами:
CloseHandle(hReadPipe);
CloseHandle(hWritePipe);
)Вопрос
Вопрос (
Если процесс обратился за чтением к пустому каналу, то он будет заблокирован, пока какой-нибудь другой процесс не запишет данные.
Если процесс обратился с записью в полный канал, то он будет заблокирован, пока какой-нибудь другой процесс не считает данные.
)Вопрос
