Прогон программы общения двух процессов через именованный канал > Функции почтовых ящиков (mailslot) Работа с почтовыми ящиками Заключение

Домашняя работа:

По операционным системам.

По теме:

Функционирование и реализация именованных каналов и почтовых ящиков в Windows 2000/XP

































Студента группы ИУ5-41

Денисова Ростислава























Содержание

Введение……………………………………………………………………3

1.	Основная характеристика именованных каналов и почтовых ящиков…………………………………………………………………………….4

1.1.	Именованные каналы………………………………………………..4

1.2.	Почтовые ящики……………………………………………………..4

2.	Реализация функций именованных каналов и почтовых ящиков……………………………………………………………………………6

2.1.	Организация соединения с помощью именованного канала……6

2.2.	Использование именованных каналов……………………………8

2.2.1.	Прогон программы общения двух процессов через именованный канал………………………………………………………………………………8

2.3.	Функции почтовых ящиков (mailslot)…………………………….10

2.3.1. Работа с почтовыми ящиками………………………………12

Заключение……………………………………………………………….15

Список используемой литературы……………………………………16


Введение

Из курса «операционные системы» известно, что для выполнения таких задач, как совместное использование данных, построение интегрированных многофункциональных приложений и т.д., различным процессам (а также различным потокам) необходимо взаимодействовать между собой. Поскольку процессы изначально задумывались как обособленные сущности, для обеспечения корректного взаимодействия процессов требуются специальные средства и действия операционной системы. 

Известно также, что в основе межпроцессного (Inter Process Communications, IPC) обмена обычно находится разделяемый ресурс (например, канал или сегмент разделяемой памяти), и, следовательно, ОС должна предоставить средства для генерации, именования, установки режима доступа и атрибутов защиты таких ресурсов. Обычно такой ресурс может быть доступен всем процессам, которые знают его имя и имеют необходимые привилегии.

Цель – изучение функционирования и реализации именованных каналов и почтовых ящиков в среде Windows.

Для достижения цели необходимо решить несколько задач:

- рассмотреть характеристики именованных каналов и почтовых ящиков;

- рассмотреть организацию соединения с помощью именованного канала;

- рассмотреть основные функции почтовых ящиков и именованных каналов;

- изучить работу с почтовыми ящиками.

Реферат состоит из введения, основной части. Заключения и списка использованной литературы. Объем работы 16 стр.





Основная характеристика

Именованные каналы

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

Именованные каналы являются объектами ядра ОС Windows, которые позволяют организовать межпроцессный обмен не только в изолированной вычислительной системе, но также и в локальной сети. 

Они обеспечивают дуплексную связь и позволяют использовать как потоковую модель, так и модель, ориентированную на сообщения. Обмен данными может быть как синхронным так и асинхронным. 



Почтовые ящики

Почтовые ящики обеспечивают только лишь однонаправленные соединения. Каждый процесс, который создает почтовый ящик, является «сервером почтовых ящиков» (mailslot server). Другие процессы, называемые «клиентами почтовых ящиков» (mailslot clients), посылают сообщения серверу, записывая их в почтовый ящик. Входящие сообщения всегда дописываются в почтовый ящик и сохраняются до тех пор, пока сервер их не прочтет. Каждый процесс может одновременно быть и сервером, и клиентом почтовых ящиков, создавая, таким образом, двунаправленные коммуникации между процессами.

Клиент может посылать сообщения на почтовый ящик, расположенный на том же компьютере, на компьютере в сети, или на все почтовые ящики с одним именем всем компьютерам выбранного домена. При этом широковещательное сообщение, транслируемое по домену, не может быть более 400 байт. В остальных случаях размер сообщения ограничивается только при создании почтового ящика сервером.


Реализация функций именованных каналов и почтовых ящиков.

Все функции именованных каналов и почтовых ящиков реализованы в DLL клиентской части подсистемы Win32 - kernel32.dll. Однако имена, задаваемые приложениями, использующими именованные каналы и почтовые ящики, определяют системное пространство имен, управляемое драйвером файловой системы именованных каналов (Named Pipes File System, NPFS.sys) и драйвером файловой системы почтовых ящиков (Mail Slots File System, MSFS.sys). Драйвер файловой системы именованных каналов создает объект-устройство, называемое «\Device\NamedPipe», и символическую ссылку к этому объекту, называемую «\??\Pipe», а драйвер файловой системы почтовых ящиков создает объект-устройство, называемое \Device\Mailslot, и символическую ссылку \??\Mailslot, указывающую на этот объект. Имена, передаваемые функции CreateFile вида «\Y\Pipe\....» и «\V\Mailslot\....», имеют префикс «\\.\», преобразуемый в «\??\», так что имена разрешаются через символическую ссылку к объекту-устройству.



Организация соединения с помощью именованного канала

Именованные каналы, как уже было сказано, используются для передачи данных между независимыми процессами или между процессами, работающими на разных компьютерах. 

Как правило, процесс сервера именованных каналов создает именованный канал с известным именем или с именем, которое будет передано клиентам. Процесс клиента именованных каналов, зная имя созданного канала, открывает его на своей стороне с учетом ограничений, указанных процессом сервера. После этого между сервером и клиентом создается соединение, по которому может производиться обмен данными в обоих направлениях. В дальнейшем наибольший интерес будут представлять именованные каналы.

При создании и получении доступа к существующему каналу необходимо придерживаться следующего стандарта имен каналов: «\\.\pipe\pipename».

Если канал находится на удаленном компьютере, то потребуется NETBIOS-имя компьютера: «\\ComputerName\pipe\pipename».

Клиентам и серверам для работы с каналами допускается использовать функции из табл. 1.

Кроме того, для работы с каналами используется функция CreateFile (для подключения к каналу со стороны клиента) и функции WriteFile и ReadFile для записи и чтения данных в/из канала соответственно.

Таблица 1.

Функции работы с каналами

Функция

Описание

CallNamedPipe

Выполняет подключение к каналу, записывает в канал сообщение, считывает из канала сообщение и затем закрывает канал

ConnectNamedPipe

Позволяет серверу именованных каналов ожидать подключения одного или нескольких клиентских процессов к экземпляру именованного канала

CreateNamedPipe

Создает экземпляр именованного канала и возвращает дескриптор для последующих операций с каналом

CreatePipe

Создает безымянный канал

DisconnectNamedPipe

Отсоединяет серверную сторону экземпляра именованного канала от клиентского процесса

GetNamedPipeHandleState

Получает информацию о работе указанного именованного канала

GetNamedPipeInfo

Извлекает свойства указанного именованного канала

PeekNamedPipe

Копирует данные их именованного или безымянного канала в буфер без удаления их из канала

SetNamedPipeHandleState

Устанавливает режим чтения и режим блокировки вызова функций (синхронный или асинхронный) для указанного именованного канала

TransactNamedPipe

Комбинирует операции записи сообщения в канал и чтения сообщения из канала в одну сетевую транзакцию

WaitNamedPipe

Ожидает, пока истечет время ожидания или пока экземпляр указанного именованного канала не будет доступен для подключения к нему





Использование именованных каналов

Сервер создает именованный канал при помощи функции CreateNamedPipe.

Помимо имени канала в форме, описанной выше, в число параметров функции входят: флаг, указывающий модель передачи данных; параметр, определяющий синхронный или асинхронный режим работы канала, а также указывающий, должен ли канал быть односторонним или двухсторонним. Кроме того, имеется необязательный дескриптор защиты, запрещающий несанкционированный доступ к именованному каналу, и параметр, определяющий максимальное число одновременных соединений по данному каналу. 

Повторно вызывая CreateNamedPipe, можно создавать дополнительные экземпляры этого же канала.

После вызова CreateNamedPipe сервер выполняет вызов ConnectNamedPipe и ждет отклика от клиентов, которые соединяются с каналом при помощи функции CreateFile или CallNamedPipe, указывая при вызове имя созданного сервером канала. Легальный клиент получает описатель, представляющий клиентскую сторону именованного канала, и работа серверной функции ConnectNamedPipe на этом завершается. 

После того как соединение по именованному каналу установлено, клиент и сервер могут использовать его для чтения и записи данных через Win32-функции ReadFile и WritePile.



Прогон программы общения двух процессов через именованный канал

Рассмотрим осуществление прогона программы общения клиента и сервера через именованный канал.

Сервер

#include <stdio.h>

#include <windows.h>

void main()

{

	PROCESS_INFORMATION piProcInfo;

	STARTUPINFO SI;

	char * ClientName = "client.exe";

	HANDLE hPipe;

	LPTSTR PipeName = TEXT("\\\\.\\pipe\\MyPipe");

	char Buff[255];

	DWORD iNumBytesToRead = 255, i;

	

	ZeroMemory(&SI, sizeof(STARTUPINFO));

	SI.cb = sizeof(STARTUPINFO); 

	ZeroMemory(&piProcInfo, sizeof(piProcInfo));

	hPipe = CreateNamedPipe( 

          PipeName,			   // имя канала

          PIPE_ACCESS_DUPLEX,       // чтение и запись из канала

          PIPE_TYPE_MESSAGE |       // передача сообщений по каналу

          PIPE_READMODE_MESSAGE |   // режим чтения сообщений 

          PIPE_WAIT,                // синхронная передача сообщений 

          PIPE_UNLIMITED_INSTANCES, // число экземпляров канала 

          4096,			   // размер выходного буфера

          4096,		          // размер входного буфера  

          NMPWAIT_USE_DEFAULT_WAIT, // тайм-аут клиента 

          NULL);                    // защита по умолчанию

	if (hPipe == INVALID_HANDLE_VALUE) 

    {

	 printf("CreatePipe failed: error code %d\n", (int)GetLastError());

        return;

    }

	if((CreateProcess(NULL, ClientName, NULL, NULL, FALSE, 0, NULL, NULL, &SI, &piProcInfo))==0)

	{

	printf("create client process: error code %d\n", (int)GetLastError());

	return;

	}

	if((ConnectNamedPipe(hPipe, NULL))==0)

	{

		printf("client could not connect\n");

		return;

	}

	ReadFile(hPipe, Buff, iNumBytesToRead, &iNumBytesToRead, NULL);

	for(i=0; i<iNumBytesToRead; i++) printf("%c",Buff[i]);



Клиент

#include <stdio.h>

#include <windows.h>



void main()

{

	HANDLE hPipe;

	LPTSTR PipeName = TEXT("\\\\.\\pipe\\MyPipe");

	DWORD NumBytesToWrite;

	char Buff[] = "Message from Client";

	hPipe = CreateFile( 

         PipeName,	      // имя канала

         GENERIC_READ |  // чтение и запись в канал

         GENERIC_WRITE, 

         0,              // нет разделяемых операций 

         NULL,           // защита по умолчанию

         OPEN_EXISTING,  // открытие существующего канала 

         0,              // атрибуты по умолчанию

         NULL);          // нет дополнительных атрибутов 

	WriteFile(hPipe, Buff, strlen(Buff), &NumBytesToWrite, NULL);

	

}  

В данном примере сервер создает канал, затем запускает процесс-клиент и ждет соединения. Далее он читает сообщение, посланное клиентом. 

Помимо перечисленных выше система представляет еще ряд полезных функций для работы с именованными каналами. Для копирования данных из именованного канала без удаления их из канала используется функция PeekNamedPipe. Функция TransactNamedPipe применяется для объединения операций чтения и записи в канал в одну операцию, которая называется транзакцией. Имеются информационные функции для определения состояния канала, например, GetNamedPipeHandleState или GetNamedPipeInfo. Полный перечень находится в MSDN.



Функции почтовых ящиков (mailslot)

Почтовые ящики предлагают легкий путь для обмена короткими сообщениями, позволяя при этом вести передачу и по локальной сети, в том числе и по всему домену. Mailslot является псевдофайлом, находящимся в памяти, и следует использовать стандартные функции для работы с файлами, чтобы получить доступ к нему. Данные в почтовом ящике могут быть в любой форме – их интерпретацией занимается прикладная программа, но их общий объем не должен превышать 64 Кб. Однако, в отличие от дисковых файлов, mail-slot являются временными – когда все дескрипторы почтового ящика закрыты, он и все его данные удаляются. Заметим, что все почтовые ящики являются локальными по отношению к создавшему их процессу; процесс не может создать удаленный mailslot.

Сообщения меньше чем 425 байт передаются с использованием дейтаграмм. Сообщения, больше чем 426 байт, используют передачу с установлением логического соединения на основе SMB-сеансов. Передачи с установлением соединения допускают только индивидуальную передачу от одного клиента к одному серверу. Следовательно, теряется возможность широковещательной трансляции сообщений от одного клиента ко многим серверам. Windows не поддерживает сообщения размером в 425 или 426 байт.

Когда процесс создает почтовый ящик, имя последнего должно иметь следующую форму: «\\.\mailslot\[path]name».

Например:

- «\\.\mailslot\taxes\bobs_comments»;

- «\\.\mailslot\taxes\petes_comments»;

- «\\.\mailslot\taxes\sues_comments».

Если необходимо отправить сообщение в почтовый ящик на удаленный компьютер, то следует воспользоваться NET-BIOS-именем: «\\ComputerName\mailslot\[path]name».

Чтобы передать сообщение всем mailslot’ам с указанным именем внутри домена, понадобится NETBIOS-имя домена: «\\DomainName\mailslot\[path]name».

Для главного домена операционной системы (домен, в котором находится рабочая станция): «\\*\mailslot\[path]name».

Клиенты и серверы, использующие почтовые ящики, при работе с ними должны пользоваться функциями, представленными в табл. 2.





Таблица 2.

Функции почтовых ящиков

Функция

Описание

Серверов



CreateMailslot

Создает почтовый ящик и возвращает его дескриптор

GetMailslotInfo

Извлекает максимальный размер сообщения, размер почтового ящика, размер следующего сообщения в ящике, количество сообщений и время ожидания сообщения при выполнении операции чтения

SetMailslotInfo

Изменение таймаута при чтении из почтового ящика

DuplicateHandle

Дублирование дескриптора почтового ящика

ReadFile, ReadFileEx

Считывание сообщений из почтового ящика

GetFileTime

Получение      даты     и   времени   создания mailslot

SetFileTime

Установка      даты     и   времени   создания mailslot

GetHandleInformation

Получение свойств дескриптора почтового ящика

SetHandleInformation

Установка свойств дескриптора почтового ящика

Клиентов



CloseHandle

Закрывает дескриптор почтового ящика для клиентского процесса

CreateFile

Создает дескриптор почтового ящика для клиентского процесса

DuplicateHandle

Дублирование дескриптора почтового ящика

WriteFile, WriteFileEx

Запись сообщений в почтовый ящик



Работа с почтовыми ящиками

Рассмотрим последовательно все операции, необходимые для корректной работы с почтовыми ящиками.

Создание почтового ящика. 

Операция выполняется процессом сервера с использованием функции CreateMailslot:

HANDLE CreateMailslot(

LPCTSTR lpName,                    // Имя почтового ящика.

DWORD nMaxMessageSize,             // Максимальный размер сообщения.

DWORD lReadTimeout,                // Таймаут операции чтения.

LPSECURITY_ATTRIBUTES              // Опции наследования и

lpSecurityAttributes               // безопасности.

);

Запись сообщений в почтовый ящик производится аналогично записи в стандартный дисковый файл. 

Следующий код иллюстрирует, как с помощью функций CreateFile, WriteFile и CloseHandle можно поместить сообщение в почтовый ящик:

LPSTR lpszMessage = "Сообщение для sample_mailslot в текущем домене.";

BOOL fResult;

HANDLE hFile;

DWORD cbWritten;

// С помощью функции CreateFile клиент открывает mailslot для записи сообщений

hFile = CreateFile("\\\\*\\mailslot\\sample_mailslot",

    GENERIC_WRITE,

    FILE_SHARE_READ, // Требуется для записи в mailslot

    (LPSECURITY_ATTRIBUTES) NULL,

    OPEN_EXISTING,

    FILE_ATTRIBUTE_NORMAL,

    (HANDLE) NULL);

if (hFile == INVALID_HANDLE_VALUE)

{

     ErrorHandler(hwnd, "Ошибка открытия почтового ящика");

     return FALSE;

}

// Запись сообщения в почтовый ящик

fResult = WriteFile(hFile,

    lpszMessage,

    (DWORD) lstrlen(lpszMessage) + 1, // включая признак конца строки

    &cbWritten,

    (LPOVERLAPPED) NULL);

if (!fResult)

{

     ErrorHandler(hwnd, "Ошибка при записи сообщения");

     return FALSE;

}

TextOut(hdc, 10, 10, "Сообщение отправлено успешно.", 21);

fResult = CloseHandle(hFile);

if (!fResult)

{

     ErrorHandler(hwnd, "Ошибка при закрытии дескриптора");

     return FALSE;

}

TextOut(hdc, 10, 30, "Дескриптор закрыт успешно.", 23);

return TRUE;



3. Чтение сообщений из почтового ящика. Создавший почтовый ящик процесс получает право считывания сообщений, из него используя дескриптор mailslot в вызове функции ReadFile.

Почтовый ящик существует до тех пор, пока не вызвана функция CloseHandle на сервере или пока существует сам процесс сервера. В обоих случаях все непрочитанные сообщения удаляются из почтового ящика, уничтожаются все клиентские дескрипторы и mailslot удаляется из памяти.

Функция считывает параметры почтового ящика:

BOOL GetMailslotInfo(

HANDLE hMailslot,                        // Дескриптор почтового ящика.

LPDWORD lpMaxMessageSize,      //  Максимальный размер

                                                     // сообщения.

LPDWORD lpNextSize,                  // Размер следующего

                                                     // непрочитанного сообщения.

LPDWORD lpMessageCount,          // Количество сообщений.

LPDWORD lpReadTimeout             // Таймаут операции чтения.

);



Функция устанавливает таймаут операции чтения:

BOOL SetMailslotInfo(

HANDLE hMailslot,                       // Дескриптор почтового ящика.

DWORD lReadTimeout                  // Новый таймаут операции

                                                    // чтения.


Заключение

Организация совместной деятельности и общения процессов является важной и актуальной задачей. К основным способам межпроцессного обмена традиционно относят каналы и разделяемую память, для организации которых используют разделяемые ресурсы. Именованные каналы, поддерживающие как потоковую модель, так и модель, ориентированную на сообщения, обеспечивают обмен данными не только в изолированной вычислительной среде, но и в локальной сети.

Почтовые ящики и именованные каналы позволяют программам обмениваться данными с процессами, исполняемыми на других машинах в сети. Каналы обеспечивают надежное двунаправленное взаимодействие между двумя процессами, независимо от того, является ли принимающая сторона локальной или удаленной. Почтовые ящики полезны для посылки широковещательных сообщений произвольному числу процессов.

В процессе написания данной работы был решен ряд задач:

- рассмотрены характеристики именованных каналов и почтовых ящиков; организация соединения с помощью именованного канала; основные функции почтовых ящиков и именованных каналов; изучена работа с почтовыми ящиками. Посредством решения поставленных задач нами было изучено функционирование и реализация именованных каналов и почтовых ящиков в среде Windows. 






Список используемой литературы

Джонсон М. Харт. Системное программирование в среде Microsoft Windows, 3-е издание, 2005.- 592 с.

Олифер, В.Г. Сетевые операционные системы / В.Г. Олифер, Н.А. Олифер. – СПб. : Питер, 2002. – 544 с.

Шеферд, Дж. Программирование на Microsoft Visual C++.NET / Дж. Шеферд, Д.Д. Круглински – СПб. : Питер, 2006. – 928 с.





1