На главную

On-line справка по Win32 API

Написать письмо
БЕСПЛАТНАЯ ежедневная online лотерея! Выигрывай каждый день БЕСПЛАТНО!
Список всех статей A-B-C-D-E-F-G-H-I-J-K-L-M-N-O-P-Q-R-S-T-U-V-W-X-Y-Z | Скачать Вниз

Server Using Completion Routines



The ReadFileEx and WriteFileEx functions provide another form of overlapped I/O. Unlike the overlapped ReadFile and WriteFile functions, which use an event object to signal completion, the extended functions specify a completion routine. A completion routine is a function that is queued for execution when the read or write operation is done. The completion routine is not executed until the thread that called ReadFileEx and WriteFileEx enters an alertable wait by calling one of the extended wait functions: WaitForSingleObjectEx, WaitForMultipleObjectsEx, or SleepEx. These functions are like the other wait functions in that they return when a specified object is in the signaled state or when a time-out interval has elapsed. However, these functions can also perform an alertable wait, which occurs when their fAlertable parameter is set to TRUE. In an alertable wait, the functions also return when a ReadFileEx or WriteFileEx completion routine is queued for execution. A server process can use the extended functions to perform a sequence of read and write operations for each client that connects to it. Each read or write operation in the sequence specifies a completion routine, and each completion routine initiates the next step in the sequence.

Like the previous example, this example is a single-threaded server process that creates a message-type pipe and uses overlapped operations. The server process differs in that it uses the extended functions ReadFileEx and WriteFileEx to perform overlapped I/O. Unlike the overlapped ReadFile and WriteFile functions, which signal an event object upon completion, the extended functions specify a completion routine, which is queued for execution when the operation is finished. The server process uses the WaitForSingleObjectEx function, which performs an alertable wait that returns when a completion routine is ready to execute. The wait function also returns when an event object is signaled, which in this example indicates that the overlapped ConnectNamedPipe operation has finished (a new client has connected).

Initially, the server process creates a single instance of the pipe and starts an overlapped ConnectNamedPipe operation. When a client connects, the server allocates a structure to provide storage for that pipe instance and then calls the ReadFileEx function to start a sequence of I/O operations to handle communications with the client. Each operation specifies a completion routine that performs the next operation in the sequence. The sequence terminates when the client is disconnected and the pipe instance closed. After starting the sequence of operations for the new client, the server creates another pipe instance and waits for the next client to connect.

The parameters of the ReadFileEx and WriteFileEx functions specify a completion routine and a pointer to an OVERLAPPED structure. This pointer is later passed to the completion routine in its lpOverLap parameter. Because the OVERLAPPED structure points to the first member in the structure allocated for each pipe instance, the completion routine can use its lpOverLap parameter to access the structure for the pipe instance.

To avoid duplication, the listing for the ConnectToNewClient subroutine is not shown; it is identical to the one used by the overlapped server process in the previous section.

#include

typedef struct
{
OVERLAPPED oOverlap;
HANDLE hPipeInst;
CHAR chBuf[BUFSIZE];
DWORD cbToWrite;
} PIPEINST, *LPPIPEINST;

BOOL CreateAndConnectInstance();
BOOL ConnectToNewClient(HANDLE, LPOVERLAPPED);
VOID GetDataToWriteToClient(LPPIPEINST);
VOID DisconnectAndClose(LPPIPEINST);
VOID WINAPI CompletedWriteRoutine(DWORD, DWORD, LPOVERLAPPED);
VOID WINAPI CompletedReadRoutine(DWORD, DWORD, LPOVERLAPPED);

HANDLE hPipe;


DWORD main(VOID)
{
HANDLE hConnectEvent;
OVERLAPPED oConnect;
LPPIPEINST lpPipeInst;
DWORD dwWait, cbBytes;
BOOL fSuccess, fPendingIO;

// Create one event object for the connect operation.

hConnectEvent = CreateEvent(
NULL, // no security attribute
TRUE, // manual reset event
TRUE, // initial state = signaled
NULL); // unnamed event object
if (hConnectEvent == NULL)
MyErrExit("CreateEvent");


oConnect.hEvent = hConnectEvent;

// Call a subroutine to create one instance, and wait for
// the client to connect.

fPendingIO = CreateAndConnectInstance(&oConnect);

while (1)
{
// Wait for a client to connect, or for a read or write
// operation to be completed, which causes a completion
// routine to be queued for execution.

dwWait = WaitForSingleObjectEx(
hConnectEvent, // event object to wait for

INFINITE, // waits indefinitely
TRUE); // alertable wait enabled

switch (dwWait)
{
// The wait is satisfied by a completed connect operation.
case 0:
// If an operation is pending, get the result of the
// connect operation.

if (fPendingIO)
{
fSuccess = GetOverlappedResult(
hPipe, // pipe handle
&oConnect, // OVERLAPPED structure

&cbBytes, // bytes transferred
FALSE); // does not wait
if (!fSuccess)
MyErrExit("ConnectNamedPipe");
}

// Allocate storage for this instance.

lpPipeInst = (LPPIPEINST) GlobalAlloc(
GPTR, sizeof(PIPEINST));
if (lpPipeInst == NULL)
MyErrExit("GlobalAlloc lpPipeInst");

lpPipeInst->hPipeInst = hPipe;


// Start the read operation for this client.
// Note that this same routine is later used as a
// completion routine after a write operation.

lpPipeInst->cbToWrite = 0;
CompletedWriteRoutine(0, 0, (LPOVERLAPPED) lpPipeInst);

// Create new pipe instance for the next client.

fPendingIO = CreateAndConnectInstance(
&oConnect);
break;

// The wait is satisfied by a completed read or write

// operation. This allows the system to execute the
// completion routine.

case WAIT_IO_COMPLETION:
break;

// An error occurred in the wait function.

default:
MyErrExit("WaitForSingleObjectEx");
}
}
return 0;
}

// CompletedWriteRoutine(DWORD, DWORD, LPOVERLAPPED)
// This routine is called as a completion routine after writing to
// the pipe, or when a new client has connected to a pipe instance. It

// starts another read operation.

VOID WINAPI CompletedWriteRoutine(DWORD dwErr, DWORD cbWritten,
LPOVERLAPPED lpOverLap)
{
LPPIPEINST lpPipeInst;
BOOL fRead = FALSE;

// lpOverlap points to storage for this instance.

lpPipeInst = (LPPIPEINST) lpOverLap;

// The write operation has finished, so read the next request (if
// there is no error).

if ((dwErr == 0) && (cbWritten == lpPipeInst->cbToWrite))
fRead = ReadFileEx(

lpPipeInst->hPipeInst,
lpPipeInst->chBuf,
BUFSIZE,
(LPOVERLAPPED) lpPipeInst,
(LPOVERLAPPED_COMPLETION_ROUTINE) CompletedReadRoutine);

// Disconnect if an error occurred.

if (! fRead)
DisconnectAndClose(lpPipeInst);
}

// CompletedReadRoutine(DWORD, DWORD, LPOVERLAPPED)
// This routine is called as an I/O completion routine after reading a
// request from the client. It gets data and writes it to the pipe.


VOID WINAPI CompletedReadRoutine(DWORD dwErr, DWORD cbBytesRead,
LPOVERLAPPED lpOverLap)
{
LPPIPEINST lpPipeInst;
BOOL fWrite = FALSE;

// lpOverlap points to storage for this instance.

lpPipeInst = (LPPIPEINST) lpOverLap;

// The read operation has finished, so write a response (if no
// error occurred).

if ((dwErr == 0) && (cbBytesRead != 0))
{
GetDataToWriteToClient(lpPipeInst);

fWrite = WriteFileEx(

lpPipeInst->hPipeInst,
lpPipeInst->chBuf,
lpPipeInst->cbToWrite,
(LPOVERLAPPED) lpPipeInst,
(LPOVERLAPPED_COMPLETION_ROUTINE) CompletedWriteRoutine);
}

// Disconnect if an error occurred.

if (! fWrite)
DisconnectAndClose(lpPipeInst);
}

// DisconnectAndClose(LPPIPEINST)
// This routine is called when an error occurs or the client closes
// its handle to the pipe.

VOID DisconnectAndClose(LPPIPEINST lpPipeInst)

{
// Disconnect the pipe instance.

if (! DisconnectNamedPipe(lpPipeInst->hPipeInst) )
MyErrExit("DisconnectNamedPipe");

// Close the handle to the pipe instance.

CloseHandle(lpPipeInst->hPipeInst);

// Release the storage for the pipe instance.

if (lpPipeInst != NULL)
GlobalFree(lpPipeInst);
}

// CreateAndConnectInstance(LPOVERLAPPED)
// This function creates a pipe instance and connects to the client.
// It returns TRUE if the connect operation is pending and FALSE if

// the connection has been completed.

BOOL CreateAndConnectInstance(LPOVERLAPPED lpoOverlap)
{
LPTSTR lpszPipename = "\\\\.\\pipe\\mynamedpipe";

hPipe = CreateNamedPipe(
lpszPipename, // pipe name
PIPE_ACCESS_DUPLEX | // read/write access
FILE_FLAG_OVERLAPPED, // overlapped mode
PIPE_TYPE_MESSAGE | // message-type pipe
PIPE_READMODE_MESSAGE | // message read mode
PIPE_WAIT, // blocking mode

PIPE_UNLIMITED_INSTANCES, // unlimited instances
BUFSIZE, // output buffer size
BUFSIZE, // input buffer size
PIPE_TIMEOUT, // client time-out
NULL); // no security attributes
if (hPipe == INVALID_HANDLE_VALUE)
MyErrExit("CreatePipe");

// Call a subroutine to connect to the new client.

return ConnectToNewClient(hPipe, lpoOverlap);
}



Пригласи друзей и счет твоего мобильника всегда будет положительным!
Предыдущая статья
 
Сайт Народ.Ру Интернет
Следующая статья
Пригласи друзей и счет твоего мобильника всегда будет положительным!

Сервер, использовавший Программы Завершения



ReadFileEx И функции WriteFileEx обеспечивают другую форму перекрытого В/В. В отличие от перекрытых ReadFile и функций WriteFile, которые используют объект события против сигнального завершения, расширенные функции определяют программу завершения. Программа завершения является функцией, которая поставлена в очередь для выполнения когда чтение или операция записи сделаны. Программа завершения не выполнена до резьбы, что назвавшее ReadFileEx и WriteFileEx вводит ожидание alertable вызывая одну из расширенных функций ожидания: WaitForSingleObjectEx, WaitForMultipleObjectsEx, или SleepEx. Эти функции являются похожий другими функциями ожидания в которых они возвращают когда определенный объект - в сигнальном состоянии или когда интервал задержки прошел. Тем не менее, эти функции могут также выполнить ожидание alertable, которое происходит когда их параметр fAlertable установлен в ИСТИНУ. В ожидании alertable, функции также возвращаются когда ReadFileEx или программа завершения WriteFileEx поставлена в очередь для выполнения. Процесс сервера может использовать расширенные функции, чтобы выполнять последовательность чтения и записывать операции для каждого клиента, который подключает к этому. Каждый был прочитан или операция записи в последовательности определяет программу завершения, и каждая программа завершения вводит следующий шаг в последовательность.

Подобно предшествующему примеру, этот пример является единственный прошитым процессом сервера, который создает сообщение-тип трубы и использует перекрытые операции. Процесс сервера отличается в том, что это использовать расширенные функции ReadFileEx и WriteFileEx, чтобы выполнять перекрытый В/В. В отличие от перекрытых ReadFile и функций WriteFile, которые сигнализируют объект события по завершении, расширенные функции определяют программу завершения, которые поставлены в очередь для выполнения когда операция завершена. Процесс сервера использует функцию WaitForSingleObjectEx, которая выполняет ожидание alertable, которое возвращается когда программа завершения готовая выполниться. Функция ожидания также возвращается когда объект события сигнализирован, какое в этом примере указывает, что перекрытая операция ConnectNamedPipe завершила ( новый клиент связал).

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

Параметры ReadFileEx и функций WriteFileEx определяют программу завершения и указатель в ПЕРЕКРЫТУЮ структуру. Этот указатель позже пройден в программу завершения в своем параметре lpOverLap. Поскольку ПЕРЕКРЫТАЯ структура указывает на первый элемент в структуре распределенной для каждого примера трубы, программа завершения может использовать свой параметр lpOverLap, чтобы иметь доступ к структуре для примера трубы.

Для того, чтобы избегать дублирования, листинг для подпрограммы ConnectToNewClient не показан; это идентично один использованное перекрытым процессом сервера в предшествующей секции.

#include <окно.h>

typedef struct
{
ПЕРЕКРЫВШЕЕ oOverlap;
ПРООПЕРИРУЙТЕ hPipeInst;
СИМВОЛ chBuf[BUFSIZE];
DWORD cbToWrite;
} PIPEINST, *LPPIPEINST;

BOOL CreateAndConnectInstance();
BOOL ConnectToNewClient(РУЧКА, LPOVERLAPPED);
АННУЛИРУЙТЕ GetDataToWriteToClient(LPPIPEINST);
АННУЛИРУЙТЕ DisconnectAndClose(LPPIPEINST);
АННУЛИРУЙТЕ WINAPI CompletedWriteRoutine(DWORD, DWORD, LPOVERLAPPED);
АННУЛИРУЙТЕ WINAPI CompletedReadRoutine(DWORD, DWORD, LPOVERLAPPED);

ПРООПЕРИРУЙТЕ hPipe;


ОСНОВА DWORD(ПУСТОТА)
{
ПРООПЕРИРУЙТЕ hConnectEvent;
ПЕРЕКРЫВШЕЕ oConnect;
LPPIPEINST lpPipeInst;
DWORD dwWait, cbBytes;
BOOL fSuccess, fPendingIO;

// Создайте один объект события для соединять операцию.

hConnectEvent = CreateEvent( НЕДЕЙСТВИТЕЛЬНАЯ, // никакая вспомогательная ИСТИНА безопасности, // руководство было восстановлено ИСТИНА события, // инициала указывать = сигнализировавшее НЕДЕЙСТВИТЕЛЬНЫМ); // безымянный объект события если (hConnectEvent == НЕДЕЙСТВИТЕЛЬНЫЙ) MyErrExit("CreateEvent");


oConnect.hEvent = hConnectEvent;

// Вызов подпрограмма, чтобы создавать один пример и ждать // клиент, чтобы соединяться.

fPendingIO = CreateAndConnectInstance(&oConnect);

пока (1)
{
// Ожидание клиент, чтобы соединяться, или для чтения или записи // операция, которые нужно завершать, который вызывает завершение // программа, которое нужно ставиться в очередь для выполнения.

dwWait = WaitForSingleObjectEx( hConnectEvent, // Объект события против ожидания

БЕСКОНЕЧНАЯ, // неопределенно ИСТИНА ожиданий); // alertable ожидание приспособленное

ключ (dwWait)
{
// Ожидание удовлетворено завершенным соединять операцию.
случай 0:
// Если операция рассматривается, получите результат // соединять операцию.

если (fPendingIO)
{
fSuccess = GetOverlappedResult( hPipe, // Ручка трубы &oConnect, // ПЕРЕКРЫТОЙ структуры

&cbBytes, // Байты передавали ЛОЖЬ); // не ожидается если (!fSuccess) MyErrExit("ConnectNamedPipe");
}

// Распределите память для этого примера.

lpPipeInst = (LPPIPEINST) GlobalAlloc( GPTR, sizeof(PIPEINST));
если (lpPipeInst == НЕДЕЙСТВИТЕЛЬНЫЙ) MyErrExit("GlobalAlloc lpPipeInst");

lpPipeInst->hPipeInst = hPipe;


// Начните операцию чтения для этого клиента.
// Отметьте, что эта та же программа позже использована как // программа завершения после записывать операции.

lpPipeInst->cbToWrite = 0;
CompletedWriteRoutine(0, 0, (LPOVERLAPPED) lpPipeInst);

// Создайте новый пример трубы для следующего клиента.

fPendingIO = CreateAndConnectInstance( &oConnect);
прерывание;

// Ожидание удовлетворено завершенным чтением или записью

// операция. Это позволяет систему, чтобы выполнять // программу завершения.

случай WAIT_IO_COMPLETION: прерывание;

// Ошибка происходила в функции ожидания.

умолчание:
MyErrExit("WaitForSingleObjectEx");
}
}
возврат 0;
}

// CompletedWriteRoutine(DWORD, DWORD, LPOVERLAPPED) // ЭТА программа вызвана как программа завершения после записи на // труба, или когда новый клиент подключил к примеру трубы. Это

// начинает другую прочитанную операцию.

ПУСТОТА WINAPI CompletedWriteRoutine(DWORD dwErr, DWORD cbWritten, LPOVERLAPPED lpOverLap)
{
LPPIPEINST lpPipeInst;
BOOL fRead = ЛОЖЬ;

// lpOverlap Указывает на память для этого примера.

lpPipeInst = (LPPIPEINST) lpOverLap;

// Записывать операция завершилась, так что прочитано следующий запрос (если // нет ошибки).

если ((dwErr == 0) && (cbWritten == lpPipeInst->cbToWrite)) fRead = ReadFileEx(

lpPipeInst->hPipeInst, lpPipeInst->chBuf, BUFSIZE, (LPOVERLAPPED) lpPipeInst, (LPOVERLAPPED_COMPLETION_ROUTINE) CompletedReadRoutine);

// Разъединитесь если ошибка происходила бы.

если (! fRead) DisconnectAndClose(lpPipeInst);
}

// CompletedReadRoutine(DWORD, DWORD, LPOVERLAPPED) // ЭТА программа вызвана как программа завершения В/В после чтения // запрос из клиента. Это получает данные и записывает это в трубу.


ПУСТОТА WINAPI CompletedReadRoutine(DWORD dwErr, DWORD cbBytesRead, LPOVERLAPPED lpOverLap)
{
LPPIPEINST lpPipeInst;
BOOL fWrite = ЛОЖЬ;

// lpOverlap Указывает на память для этого примера.

lpPipeInst = (LPPIPEINST) lpOverLap;

// Операция чтения завершилась, так что запись ответ (если никакая // ошибка не происходила бы).

если ((dwErr == 0) && (cbBytesRead != 0))
{
GetDataToWriteToClient(lpPipeInst);

fWrite = WriteFileEx(

lpPipeInst->hPipeInst, lpPipeInst->chBuf, lpPipeInst->cbToWrite, (LPOVERLAPPED) lpPipeInst, (LPOVERLAPPED_COMPLETION_ROUTINE) CompletedWriteRoutine);
}

// Разъединитесь если ошибка происходила бы.

если (! fWrite) DisconnectAndClose(lpPipeInst);
}

// DisconnectAndClose(LPPIPEINST) // ЭТА программа вызвана когда ошибка происходит или клиент закрывает // ручку в трубу.

ПУСТОТА DisconnectAndClose(LPPIPEINST lpPipeInst)

{
// Разъедините пример трубы.

если (! DisconnectNamedPipe(lpPipeInst->hPipeInst) ) MyErrExit("DisconnectNamedPipe");

// Закройте ручку в пример трубы.

CloseHandle(lpPipeInst->hPipeInst);

// Выпустите память для примера трубы.

если (lpPipeInst != НЕДЕЙСТВИТЕЛЬНЫЙ) GlobalFree(lpPipeInst);
}

// CreateAndConnectInstance(LPOVERLAPPED) // ЭТА функция создает пример трубы и подключает к клиенту.
// Это возвращает ИСТИНУ если соединять операцию рассматривает и ЛОЖЬ если

// связь завершена.

BOOL CreateAndConnectInstance(LPOVERLAPPED lpoOverlap)
{
LPTSTR lpszPipename = "\\\\.\\pipe\\mynamedpipe";

hPipe = CreateNamedPipe( lpszPipename, // Имя трубы PIPE_ACCESS_DUPLEX | // прочитавшее/доступ записи FILE_FLAG_OVERLAPPED, // перекрытый режим PIPE_TYPE_MESSAGE | // сообщение-тип трубы PIPE_READMODE_MESSAGE | // сообщение было прочитано режим PIPE_WAIT, // блокировка режима

PIPE_UNLIMITED_INSTANCES, // неограниченные примеры BUFSIZE, // выходной буферный размер BUFSIZE, // входной буферный размер PIPE_TIMEOUT, // задержка клиента НЕДЕЙСТВИТЕЛЬНЫЙ); // никакая безопасность не приписывается если (hPipe == INVALID_HANDLE_VALUE) MyErrExit("CreatePipe");

// Вызов подпрограмма, чтобы подключать к новому клиенту.

возвращайте ConnectToNewClient(hPipe, lpoOverlap);
}



Вверх Version 1.3, Oct 26 2010 © 2007, 2010, mrhx Вверх
 mrhx software  Русский перевод OpenGL  Русский перевод Win32 API
 
Используются технологии uCoz