Программирование на Delphi
м будет
выведено соответствующее сообщение. Если значение не нулевое, то будет
вызвана функция MapViewOfFile. Дескриптор hMappedFile является первым
параметром этой функции и связывает созданный отображаемый файл с текущим
процессом. Если функция завершится успешно, то в переменную pSharedBuf
будет помещен начальный адрес памяти, по которому располагаются данные
объекта файлового отображения с именем SharedBlock. Если функция отработает
с ошибкой, то значение, возвращаемое функцией MapViewOfFile будет равно
nil, в этом случае будет показано сообщение, констатирующее этот факт.
Совместное использование отображаемых данных
Чтобы разделить между процессами память, выделенную из страничного файла
операционной системы, каждый процесс, участвующий в разделении, должен
отобразить один и тот же фрагмент одного и того же файла. Такой результат
может быть достигнут передачей во всех указанных процессах одинаковых
параметров для функций CreateFileMapping и MapViewOfFile. Указатель,
возвращаемый последней функцией, вы можете впоследствии считывать или
записывать согласно своим потребностям. Если данные, связанные с этим
указателем, доступны одному из процессов, то они также доступны и другим
процессам.
Займемся очередным "клонированием" нашего примера с передачей данных о
времени и свободной памяти. Общим для клиента и сервера теперь является
описанный выше код по открытию и отображению файла. Он описан как реакция
на событие формы onCreate. Когда запускается программа и создается форма,
соответственно создается и подключается отображаемый файл. Код выглядит
так:
procedure TSrvForm.FormCreate (Sender: TObjecr);
begin
hFileMapObj:=CreateFiieMapping(MAXDWORD, nil, PAGE_READWRITE, 0, 25,
'SharedMem');
if (hFiieMapObj:=0) then ShowMessage('Error: cannot map this file')
else begin
pSharedBuf:=MapViewOfFile(hFiieMapObj,FILE_MAP_WRITE,0,0,0);
if (pSharedBuf = nil) then
ShowMessage ('Error: pSharedBuf is nil');
end;
end;
Приведенный выше код работает точно так, как описано выше в разделе
"Подключение объекта файлового отображения к адресному пространству".
Единственным отличием является лишь то, что объявления переменных
hFileMapObj и pSharedBuf перенесены в раздел var секции interface так, как
это показано ниже:
interface
var Form1: TForm1;
hFileMapObj: THandle;
pSharedBuf; Pointer;
implementation
Компоненты типа TTimer есть и у клиента и у сервера. При каждом очередном
событии от этого компонента сервер помещает нужные данные в совместно
используемую область памяти:
type
pDataRecord = ^TDataRecord;
TDataRecord = record
DateTime : TDateTime;
Mem : Cardinal ;
end;
procedure TServerForm.Timer1Timer(Sender: TObject);
var ms : TMemoryStatus;
begin
GlobalMemoryStatus (ms);
pDataRecord(pSharedBuf)^.DateTime:= Now;
pDataRecord(pSharedBuf)^.Mem := ms.dwAvailPageFile + ms.dwAvaiiPhys;
end;
а клиент — читает эти данные, если нажата соответствующая кнопка:
procedure TClientForm.TimerITimerfSender: TObject);
begin
if MemSpeedButton.Down then MemSpeedButton.Caption:=
Format('%8dK',[pDataRecord(pSharedBuf)^.Mem div 1024]);
if TimeSpeedButton.Down then TimeSpeedButton.Caption:=
TimeToStr(pDataRecord(pSharedBuf)^.DateTime);
end;
Последним штрихом станет восстановление надписи на кнопке после того, как
она снова нажата пользователем:
procedure TClientForm.TimeSpeedButtonClick (Sender: TObject);
begin
if not TimeSpeedButton.Down then TimeSpeedButton.Caption:='Time';
end;
procedure TClientForm.Mem.SpeedButtonClick(Sender: TObject);
begin
if not MemSpeedButton. Down then MemSpeedButton.Caption:='Memory';
end;
В рассматриваемой программе есть несколько операторов, необходимых для
прекращения отображения данных и освобождения объекта файлового
отображения. Эти операторы обсуждаются в следующем разделе.
Прекращение отображения данных и закрытие объекта файлового отображения
Последние две функции, имеющие отношение к объекту файлового отображения,
называются UnMapViewOfFile И CloseHandle. ФУНКЦИЯ UnMapViewOfFile делает
то, что подразумевает ее название. Она прекращает отображение в адресное
пространство процесса того файла, который перед этим был отображен при
помощи функции MapViewOfFile. Функция CloseHandle также делает то, что
подразумевает ее название; она закрывает дескриптор, в нашем случае это
дескриптор объекта файлового отображения, возвращаемый функцией
CreateFileMapping.
Функция UnMapViewOfFile должна вызываться перед функцией CloseHandle
Функции UnMapViewOfFile передается единственный параметр типа указатель:
procedure TCIientForm.FormDestroy(Sender: TObject);
begin
UnMapViewOfFiie (pSharedBuf) ;
CloseHandle (hFileMapObj);
end;
Помимо возможности совместного доступа отображаемые файлы позволяют заметно
ускорить доступ к файлам, особенно большого размера, являясь очень мощным
инструментом доступа к данным.
Каналы
Протокол DDE пережил полосу своего расцвета, и хотя впоследствии появилась
его сетевая версия (Network DDE, или NDDE), стандартом де-факто она не
стала. Одним из кандидатов на замену DDE стал механизм каналов (pipes). О
его роли говорит хотя бы то, что это один из основных протоколов работы
такого продукта, как Microsoft SQL Server.
Сразу оговоримся, что каналы бывают двух видов — именованные (named pipes)
и безымянные (anonymous pipes). Вторые не предназначены для связи между
самостоятельными приложениями и представляют собой, так сказать, рудимент
Win32 API. В этой книге рассматриваются только именованные каналы.
И еще одна очень важная оговорка. Каналы рассматривались Microsoft как
протокол для организации клиент-серверных приложений. Поэтому их серверная
часть реализована только в среде Windows NT и не поддерживается в Windows
95/98; клиенты могут быть созданы во всех этих ОС.
Канал можно представить себе как среду, через которую могут обмениваться
данными два приложения. Обмен данными может быть как односторонним, так и
двухсторонним. Тем не менее, одно из приложений играет роль сервера (оно
создает канал), другое (или другие) лишь подключается к нему. Противоречия
с вышесказанной фразой о двух приложениях здесь нет: на сервере канал виден
как ресурс с единственным уникальным именем. Когда к серверу подключается
очередной клиент, для него создается уникальный экземпляр канала со своими
дескриптором, буфером и т, п. Но имя канала для всех клиентов одинаково.
Имя канала записывается в соответствии с так называемым соглашением UNC
(Universal Naming Convention). Выглядеть оно должно так:
servernamepipepipename
де servernanie — сетевое имя компьютера — сервера,
ipename — имя канала.
В случае, если клиенту нужно подключиться к серверу на том же компьютере,
его сетевое имя заменяется точкой:
.pipepipename
Максимальная длина имени канала ограничена 256 символами; строчные и
прописные буквы не отличаются.
Для программиста алгоритмы создания серверного и клиентского "концов"
канала отличаются. Для создания сервера применяются специальные функции Win
32 API; клиентский же конец открывается как обычный файл и работа с ним
также напоминает работу с файлом. Неудивительно, что в дальнейшем мы
"упрячем" эти функции в класс Delphi — потомок HandleStream, ближайшего
родственника файлового потока TFileStream.
Пока же рассмотрим искомые функции API. Главная из них для нас следующая:
function CreateNainedPipe(lpName: PChar;
dwOperiMode,
dwPipeMode,
nMaxInstances,
nOutBufferSize,
nInBufferSize,
nDefauitTimeOut: DWORD;
lpSecurityAttributes:PSecurityAttributes):THandle;
Она создает серверный конец канала с именем lpName. Остальные параметры
перечислены в табл. 8.1.
Параметры функции createNamedPipe
Параметр Назначение
dwOpenMode
Режим открытия. Флаги:
PIPE_ACCESS_DUPLEX — двунаправленный обмен данными
PIPE_ACCESS_INBOUND — только от клиента к серверу
PIPE_ACCESS_OUTBOUND — только от сервера к клиенту
FILE_FLAG_WRITE_THROUGH — запись данных, минуя кэш
FILE_FLAG_OVERLAPPED — режим отложенной операции ввода/ вывода
dwPipeMode
Режим работы канала. Флаги:
PIPE_TYPE_BYTE — запись в режиме потока байт
PIPE TYPE_MESSAGE — запись в режиме потока сообщений
PIPE_READMODE_BYTE — чтение в режиме потока байт
PIPE_READMODE_MESSAGE — чтение в режиме потока сообщений
PIPE_WAIT — функции ввода/вывода не будут возвращать управление до
завершения операции
PIPE_NOWAIT — функции ввода/вывода возвращают управление немедленно
nMaxinstances
Максимальное количество открываемых экземпляров канала, от 1 до
PIPE_UNLIMITED_INSTANCES
nOutBufferSize
Размер буфера для записи
nInBufferSize
Размер буфера для чтения
nDefauitTimeOut
Задает время ожидания конца операции ввода/вывода в канале (в мс)
IpSecurityAttributes
Указатель на структуру Windows NT, содержащую информацию о правах доступа к
каналу Pежимы потока байт и потока сообщений не слишком отличаются друг от
друга — в первом случае система смешивает данные от различных операций
чтения/записи в единый поток, во втором — разделяет их на отдельные порции.
Канал в режиме PIPE_TYPE_BYTE может работать на чтение только в режиме
чтения PIPE_READMODE_BYTE, канал в режиме PIPE_TYPE_MESSAGE — в обоих
режимах чтения.
Функция
function ConnectNainedPipe(hNamedPipe: THandle;
lpOverlapped: POverlapped): BO
| | скачать работу |
Программирование на Delphi |