ВУЗ: Не указан
Категория: Не указан
Дисциплина: Не указана
Добавлен: 12.06.2019
Просмотров: 100
Скачиваний: 1
Лабораторная работа № 5
Студента ИТ 14-1 Красовского Абхая
Технологии обмена данными между процессами: каналы
Вариант №9
Цель: Получить навыки в следующих предметных областях:
-
создание и использование каналов;
-
создание и использование процессов
Индивидуальное задание
Реализовать задание взаимодействия потоков, процессов и канала.
Код сервера:
#include <windows.h>
#include <process.h>
#include <iostream>
#define BUFSIZE 4096
using namespace std;
void ThreadF(LPVOID);
void main()
{
setlocale(LC_ALL, "rus");
bool fConnected;
HANDLE hPipe, hThread;
char *pipename = "\\\\.\\pipe\\MyPipe";
// Мы в цикле создаем экземпляр канала и ожидаем подключение клиента.
// Когда клиент подключится, мы создаем отдельный поток для работы с ним.
cout << "Сервер готов!" << endl;
while (true)
{
hPipe = CreateNamedPipe(pipename, // имя канала
PIPE_ACCESS_DUPLEX, // дуплексный режим (чтения и записи)
PIPE_TYPE_MESSAGE | PIPE_READMODE_MESSAGE | PIPE_WAIT, // запись в виде сообщений // чтение в виде сообщений // блокирующий режим
PIPE_UNLIMITED_INSTANCES, // максимальное число экземпляров
BUFSIZE, // размер выходного буфер
BUFSIZE, // размер входного буфер
0, // тайм-аут
NULL); // атрибуты безопасности
if (hPipe == INVALID_HANDLE_VALUE)
cout << ("Ошибка при создании канала", GetLastError()) << endl;
// Ждем подключения клиента
fConnected = ConnectNamedPipe(hPipe, NULL) ? true: (GetLastError() == ERROR_PIPE_CONNECTED);
//(логическое выражение) ? (если выражение истинно) : (если выражение ложно)
if (fConnected)
{
cout << "Получено новое соединение." << endl;
// Создаем поток для клиента
hThread = (HANDLE)_beginthreadex(NULL, 0, (unsigned int(_stdcall*)(void*))ThreadF, (void*)hPipe, 0, NULL); // функция создания потока с возможной проверкой его создания
if (hThread == NULL)
cout << "Ошибка при создании потока клиента" << endl;
else
CloseHandle(hThread);
} else
// Клиент не может подключиться, закрываем канал
CloseHandle(hPipe);
}
}
void ThreadF(LPVOID lpvParam)
{
char StringIn[BUFSIZE];
char StringOut[BUFSIZE];
DWORD BytesRead, ReplyBytes, Written;
BOOL fSuccess;
HANDLE hPipe = (HANDLE) lpvParam;
while (true)
{
// Читаем запрос от клиента
fSuccess = ReadFile(
hPipe, //собственно указатель на файл
StringIn, // указатель на буфер - куда записываем считанные данные
sizeof(StringIn), //объем считываемых данных, не может превышать размер буфера
&BytesRead, //фактический размер считанных данных
NULL); // флаг режима доступа к файлу - NULL(синхронный)
if (! fSuccess || BytesRead == 0)
break;
// Приведем полученную строку к верхнему регистру
for (ReplyBytes = 0; (ReplyBytes < BUFSIZE - 1) && (StringIn[ReplyBytes] != 0); ReplyBytes++)
StringOut[ReplyBytes] = toupper(StringIn[ReplyBytes]);
StringOut[ReplyBytes++] = '\0';
// Пишем ответ в канал
fSuccess = WriteFile(
hPipe,
StringOut, // откуда писать
ReplyBytes, // сколько писать
&Written, // число записанных байт
NULL);
if (! fSuccess || ReplyBytes != Written)
break;
}
// Выполним принудительный сброс буферов на сторону клиента
FlushFileBuffers(hPipe); // очищает буфер для указанного файла и заставляет все буферизированные данные быть записанными в этом файле
DisconnectNamedPipe(hPipe); // отсоединение клиента от сервера
CloseHandle(hPipe);
cout << "Клиент прекращает работу" << endl;
}
Код клиента:
#include <windows.h>
#include <iostream>
#include <conio.h>
#define BUFSIZE 512
using namespace std;
void main()
{
setlocale(LC_ALL, "rus");
char *pipename = "\\\\.\\pipe\\MyPipe";
HANDLE hPipe;
char inputBuffer[BUFSIZE];
char Buf[BUFSIZE];
BOOL fSuccess;
DWORD Mode;
char ch;
// Пробуем открыть именованный канал; ждем экземпляр канала, если необходимо
while (true)
{
hPipe = CreateFile(pipename, // Указатель на имя файла
GENERIC_READ | GENERIC_WRITE, //Параметры доступа
0, //Разделяемый доступ
NULL, //безопасность
OPEN_EXISTING, // Описание
0, // Атрибуты файла
NULL); // Файл шаблона
if (hPipe != INVALID_HANDLE_VALUE) break;
// Все экземпяры канала заняты, ждем
if (!WaitNamedPipe(pipename, NMPWAIT_WAIT_FOREVER))
cout << "Невозможно получить доступ к каналу." << endl;
}
cout << "Поздравляю! Вы подключились серверу." << endl;
// Мы подключились к каналу. Переведем его в режим чтения сообщений
Mode = PIPE_READMODE_MESSAGE; // чтение в виде сообщений
if (!(fSuccess = SetNamedPipeHandleState(hPipe, &Mode, NULL, NULL))) // функция устанавливает режим чтения и режим блокировки указанного имени канала
cout << "SetNamedPipeHandleState failed with error" << endl;
do {
cout << "Введите строку: " << endl;
cin >> inputBuffer;
// Шлем сообщение
if (!(fSuccess = WriteFile(
hPipe, //собственно указатель на файл
inputBuffer, // буфер сообщения
strlen(inputBuffer)+1, // размер сообщения (+1 - закрывающий ноль в строке)
&Mode, // число фактически переданных байт
NULL))) // флаг режима доступа к файлу, NULL(синхронный)
cout << "WriteFile failed with error" << endl;
if (!(fSuccess = ReadFile(
hPipe,
Buf, // буфер куда поместить ответ
BUFSIZE, // размер буфера
&Mode, // число фактически прочитанных байт
NULL))) // флаг режима доступа к файлу, NULL(синхронный)
{
cout << "ReadFile failed with error" << endl;
break;
}
cout << "Ответ сервера: " << Buf << endl;
cout << "Повторить (Y/N)? ";
cin >> ch;
} while ('N' != toupper(ch));
CloseHandle(hPipe);
}
Р езультат: