Добавил:
Upload Опубликованный материал нарушает ваши авторские права? Сообщите нам.
Вуз: Предмет: Файл:
лаба12.doc
Скачиваний:
26
Добавлен:
12.11.2019
Размер:
173.06 Кб
Скачать

5.Пример сервера с процедурами завершения

#include <windows.h>

#include <stdio.h>

#define BUFSIZE 200

#define PIPE_TIMEOUT 100

typedef struct

{

OVERLAPPED oOverlap;

HANDLE hPipeInst;

CHAR chBuf[BUFSIZE];

DWORD cbToWrite;

} PIPEINST, *LPPIPEINST;

BOOL CreateAndConnectInstance(OVERLAPPED*);

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;

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

hConnectEvent = CreateEvent(

NULL, // no security attribute

TRUE, // manual reset event

TRUE, // initial state = signaled

NULL); // unnamed event object

if (hConnectEvent == NULL)

{

printf("CreateEvent Error!");

exit(1);

}

oConnect.hEvent = hConnectEvent;

// Вызов подпрограммы для создания одного экземпляра канала и

// ожидания подсоединения клиента.

fPendingIO = CreateAndConnectInstance(&oConnect);

while (1)

{

// Ожидание подсоединения клиента, или завершения операций

// для чтения или записи,которая ставит в очередь выполнение

// процедуры завершения

//

dwWait = WaitForSingleObjectEx(

hConnectEvent, // событие которое ожидается

INFINITE, // ждать бесконечно

TRUE); // для выполнения процедур завершения

switch (dwWait)

{

case 0:

// Если операция не завершена - получить результат

// операции подсоединения

if (fPendingIO)

{

fSuccess = GetOverlappedResult(

hPipe, // дескриптор канала

&oConnect, // OVERLAPPED структура

&cbBytes, // количество перенесенных байт

FALSE); // без ожидания

if (!fSuccess)

{

printf("ConnectNamedPipe Error!");

exit(1);

}

}

// Выделить память под экземпляр.

lpPipeInst = (LPPIPEINST) GlobalAlloc(

GPTR, sizeof(PIPEINST));

if (lpPipeInst == NULL)

{

printf("GlobalAlloc lpPipeInst Error!");

exit(1);

}

lpPipeInst->hPipeInst = hPipe;

// Запуск операции чтения для данного клиента

// Та же самая подпрограмма вызывается после

// операции записи как подпрограмма завершения операции

lpPipeInst->cbToWrite = 0;

CompletedWriteRoutine(0, 0, (LPOVERLAPPED) lpPipeInst);

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

fPendingIO = CreateAndConnectInstance(

&oConnect);

break;

// Ожидание заканчивается при завершении операции чтения или

// записи. Это позволяет системе использовать подпрограмму завершения

case WAIT_IO_COMPLETION:

break;

// Произошла ошибка в функции ожидания.

default:

printf("WaitForSingleObjectEx Error");

exit(1);

}

}

return 0;

}

// Это подпрограмма вызывается как процедура завершения после записи в канал,

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

// Запускается новая операция чтения

VOID WINAPI CompletedWriteRoutine(DWORD dwErr, DWORD cbWritten,

LPOVERLAPPED lpOverLap)

{

LPPIPEINST lpPipeInst;

BOOL fRead = FALSE;

// lpOverlap указывает на память для экземпляра

lpPipeInst = (LPPIPEINST) lpOverLap;

// Операция записи завершена, поэтому читаем следующий запрос

// (если нет ошибок).

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

fRead = ReadFileEx(

lpPipeInst->hPipeInst,

lpPipeInst->chBuf,

BUFSIZE,

(LPOVERLAPPED) lpPipeInst,

(LPOVERLAPPED_COMPLETION_ROUTINE) CompletedReadRoutine);

// Отсоединение если произошла ошибка

if (! fRead)

DisconnectAndClose(lpPipeInst);

}

// Данная подпрограмма вызыввается, как процедура завершения после чтения

// запроса от клиента. Получает данные и записывает в канал.

VOID WINAPI CompletedReadRoutine(DWORD dwErr, DWORD cbBytesRead,

LPOVERLAPPED lpOverLap)

{

LPPIPEINST lpPipeInst;

BOOL fWrite = FALSE;

// lpOverlap указывает на память для экземпляра.

lpPipeInst = (LPPIPEINST) lpOverLap;

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

if ((dwErr == 0) && (cbBytesRead != 0))

{

GetDataToWriteToClient(lpPipeInst);

fWrite = WriteFileEx(

lpPipeInst->hPipeInst,

lpPipeInst->chBuf,

lpPipeInst->cbToWrite,

(LPOVERLAPPED) lpPipeInst,

(LPOVERLAPPED_COMPLETION_ROUTINE) CompletedWriteRoutine);

}

// Отсоединение если произошла ошибка.

if (! fWrite)

DisconnectAndClose(lpPipeInst);

}

// Данная подпрограмма вызывается, если произошла ошибка

// или клиент закрывает дескриптор канала

VOID DisconnectAndClose(LPPIPEINST lpPipeInst)

{

// Отсоединить экземпляр канала.

if (! DisconnectNamedPipe(lpPipeInst->hPipeInst) )

{

printf("DisconnectNamedPipe Error!");

exit(1);

}

// Закрыть дескриптор канала.

CloseHandle(lpPipeInst->hPipeInst);

// Освободить память выделенную для канала

if (lpPipeInst != NULL)

GlobalFree(lpPipeInst);

}

// Данная функция создает экземпляр канала и соединяется с клиентом.

// Возвращает TRUE если операция соединения не завершена и FALSE, если

// соединение завершено.

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, // тайм аут клиента

NULL); // нет атрибутов безопасности

if (hPipe == INVALID_HANDLE_VALUE)

{

printf("CreatePipe Error!");

exit(2);

}

// выхов процедуры для подсоединения нового клиента

return ConnectToNewClient(hPipe, lpoOverlap);

}

// Эта функция вызывается для запуска асинхронной операции соединения

// Возвращает TRUE если операция не завершена или FALSE если соединение установлено

BOOL ConnectToNewClient(HANDLE hPipe, LPOVERLAPPED lpo)

{

BOOL fConnected, fPendingIO = FALSE;

// Запуск асинхронной операции соединения для данного экземпляра канала

fConnected = ConnectNamedPipe(hPipe, lpo);

// Асинхронный ConnectNamedPipe(hPipe, lpo) должен возвращать 0

if (fConnected)

{

printf("Connect NamedPipe Error");

exit(1);

}

switch (GetLastError())

{

// Асинхронное соединение в процессе выполнения.

case ERROR_IO_PENDING:

fPendingIO = TRUE;

break;

// Клиент подсоединен - установка события

case ERROR_PIPE_CONNECTED:

if (SetEvent(lpo->hEvent))

break;

// Если произошла ошибка во время операции соединения

default:

printf("ConnectNamedPipe Error");

exit(1);

}

return fPendingIO;

}

VOID GetDataToWriteToClient(LPPIPEINST pPipe)

{

lstrcpy(pPipe->chBuf,"hi to all!");

pPipe->cbToWrite = lstrlen(pPipe->chBuf) + 1;

}

Соседние файлы в предмете [НЕСОРТИРОВАННОЕ]