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

4.Пример сервера с асинхронным вводом – выводом

#include "stdafx.h"

#include <windows.h>

#include <stdio.h>

#define CONNECTING_STATE 0

#define READING_STATE 1

#define WRITING_STATE 2

#define INSTANCES 4

#define BUFSIZE 200

#define PIPE_TIMEOUT 200

typedef struct

{

OVERLAPPED oOverlap;

HANDLE hPipeInst;

CHAR chBuf[BUFSIZE];

DWORD cbToWrite;

DWORD dwState;

BOOL fPendingIO;

} PIPEINST, *LPPIPEINST;

VOID DisconnectAndReconnect(DWORD);

BOOL ConnectToNewClient(HANDLE, LPOVERLAPPED);

VOID GetDataToWriteToClient(LPPIPEINST pPipe)

{

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

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

}

PIPEINST Pipe[INSTANCES];

HANDLE hEvents[INSTANCES];

int main(int argc, char* argv[])

{

DWORD i, dwWait, cbBytes, dwErr;

BOOL fSuccess;

LPTSTR lpszPipename = "\\\\.\\pipe\\mynamedpipe";

// Цикл инициализации - создает несколько экземпляров

// именнованных каналов

// Асинхронная операция ConnectNamedPipe

// запускается для каждого экземпляра

for (i = 0; i < INSTANCES; i++)

{

// Создание объекта события для экземпляра - канала

hEvents[i] = CreateEvent(

NULL, // no security attribute

TRUE, // manual-reset event

TRUE, // initial state = signaled

NULL); // unnamed event object

if (hEvents[i] == NULL)

{

printf("CreateEvent Error");

exit(1);

}

Pipe[i].oOverlap.hEvent = hEvents[i];

Pipe[i].hPipeInst = CreateNamedPipe(

lpszPipename, // название канала

PIPE_ACCESS_DUPLEX | // доступ на чтение - запись

FILE_FLAG_OVERLAPPED, // асинхронный ружим

PIPE_TYPE_MESSAGE | // тип канала - обмен сообщениями

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

PIPE_WAIT, // блокирующий режим

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

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

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

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

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

if (Pipe[i].hPipeInst == INVALID_HANDLE_VALUE)

{

printf("CreatePipe Error");

exit(1);

}

// посоединение нового клиента

Pipe[i].fPendingIO = ConnectToNewClient(

Pipe[i].hPipeInst,

&Pipe[i].oOverlap);

Pipe[i].dwState = Pipe[i].fPendingIO ?

CONNECTING_STATE : // в состоянии соединения ?

READING_STATE; // готов к чтению

}

while (1)

{

// Ожидание установки события - означающее

// окончания асинхронного чтения, записи или операции соединения

dwWait = WaitForMultipleObjects(

INSTANCES, // количество объектов событий

hEvents, // массив объектов событий

FALSE, // не ждать всех

INFINITE); // ожидание бексонечно

// dwWait - показывает какой канал завершил операцию.

i = dwWait - WAIT_OBJECT_0; // определяем номер канала

if (i < 0 || i > (INSTANCES - 1))

{

printf("Index out of range");

exit(1);

}

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

if (Pipe[i].fPendingIO)

{

fSuccess = GetOverlappedResult(

Pipe[i].hPipeInst, // дескриптор канала

&Pipe[i].oOverlap, // OVERLAPPED структура

&cbBytes, // байт перенесено

FALSE); // не ждать завершения операции

switch (Pipe[i].dwState)

{

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

case CONNECTING_STATE:

if (! fSuccess)

printf("ConnectNamedPipe Error");

Pipe[i].dwState = READING_STATE;

break;

// выполняется операция чтения

case READING_STATE:

if (! fSuccess || cbBytes == 0)

{

DisconnectAndReconnect(i);

continue;

}

Pipe[i].dwState = WRITING_STATE;

break;

// выполняется операция записи

case WRITING_STATE:

if (! fSuccess || cbBytes != Pipe[i].cbToWrite)

{

DisconnectAndReconnect(i);

continue;

}

Pipe[i].dwState = READING_STATE;

break;

default:

printf("Invalid pipe state");

exit(1);

}

}

// состояние канала определяет следующую операцию

switch (Pipe[i].dwState)

{

// READING_STATE:

// Экземпляр канала соединен с клиентом и готов

// прочесть запрос от клиента

case READING_STATE:

fSuccess = ReadFile(

Pipe[i].hPipeInst,

Pipe[i].chBuf,

BUFSIZE,

&cbBytes,

&Pipe[i].oOverlap);

// Операция чтения завершена успешна.

if (fSuccess && cbBytes != 0)

{

Pipe[i].fPendingIO = FALSE;

Pipe[i].dwState = WRITING_STATE;

continue;

}

// Операция чтения не завершена.

dwErr = GetLastError();

if (! fSuccess && (dwErr == ERROR_IO_PENDING))

{

Pipe[i].fPendingIO = TRUE;

continue;

}

// Произошла ошибка; отсоединить от клиента.

DisconnectAndReconnect(i);

break;

// WRITING_STATE:

// Запрос был успешно прочитан (получен) от клиента

// Получить данные для ответа и записать (послать) в клиента

case WRITING_STATE:

GetDataToWriteToClient(&Pipe[i]);

fSuccess = WriteFile(

Pipe[i].hPipeInst,

Pipe[i].chBuf,

Pipe[i].cbToWrite,

&cbBytes,

&Pipe[i].oOverlap);

// Операция записи завершена успешно.

if (fSuccess && cbBytes == Pipe[i].cbToWrite)

{

Pipe[i].fPendingIO = FALSE;

Pipe[i].dwState = READING_STATE;

continue;

}

// Операция записи не завершена.

dwErr = GetLastError();

if (! fSuccess && (dwErr == ERROR_IO_PENDING))

{

Pipe[i].fPendingIO = TRUE;

continue;

}

// Произошла ошибка; отсоединить от клиента.

DisconnectAndReconnect(i);

break;

default:

printf("Invalid pipe state");

exit(1);

}

}

return 0;

}

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

// (свой дескриптор к каналу). Отсоединиться от данного клиента, затем вызвать

// ConnectNamedPipe для ожидания подсоединения другог клиента

VOID DisconnectAndReconnect(DWORD i)

{

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

if (! DisconnectNamedPipe(Pipe[i].hPipeInst) )

{

printf("DisconnectNamedPipe Error");

exit(1);

}

// Подсоединение нового клиента.

Pipe[i].fPendingIO = ConnectToNewClient(

Pipe[i].hPipeInst,

&Pipe[i].oOverlap);

Pipe[i].dwState = Pipe[i].fPendingIO ?

CONNECTING_STATE : // в процессе соединения

READING_STATE; // готов к чтению

}

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

// Возвращает TRUE если операция в процессе выполнения и

// FALSE если соединение установлено

BOOL ConnectToNewClient(HANDLE hPipe, LPOVERLAPPED lpo)

{

BOOL fConnected, fPendingIO = FALSE;

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

fConnected = ConnectNamedPipe(hPipe, lpo);

// Асинхронная функция ConnectNamedPipe должа возвращать ноль.

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;

}

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