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

3.3. Решения при разработке сервера именованного канала

При разработке сервера три основных решения:

    1. Многопоточный сервер – для каждого клиента заводится отдельный поток, который обрабатывает запрос клиента. Каждый клиент работает со своим экземпляром канала.

    2. Сервер с асинхронным вводом- выводом – заводится массив экземпляров канала для каждого клиента. Асинхронно вызывается соединение с клиентом ().C помощью функции WaitForMultipleObjects ожидается выполнение операции клиента (соединение, чтение, запись). По текущей операции клиента определяется следующая операция, которую клиенту необходимо выполнить (после соединения – чтение запроса клиента – после чтения – запись ответа клиенту).

    3. Сервер с процедурами завершения – схема с асинхронными операциями ввода – вывода, в дополнение после каждой операции автоматически вызывается системой процедура завершения. Для операции чтения процедура завершения – функция записи ответа сервера в канал.

Примечание: Операции запись и чтения из канала можно объединить одной функцией

TransactNamedPipe. Операции открытия канала и ожидания, записи, чтения закрытия канала функцией – CallNamedPipe.

При именовании канала иметь в виду, что если канал создается локально (сервер или клиент на той же машине) \.\pipe\имя_канала. Если обращение к каналу идет с другой машины, то \имя_машины\pipe\имя_канала.

4. Порядок выполнения работы

  1. Создать сервер для обработки информации от клиентов. В качестве данных для обработки строка символов, в которую после каждого символа помещают пробел и передают обратно клиенту. При получении строки отобразить ее на экране.

  2. Создать клиента, который отсылает на обработку серверу массив строк. Осуществить вывод строк до обработки и после обработки.

  3. Реализовать разные виды серверов.

  4. Реализовать «чат» на основе одного из типов серверов. То есть осуществить связь клиентов между собой, так чтобы каждый из клиентов получал строку отосланную другим клиентом.

  5. Для выполнения заданий использовать примеры из приложений.

5.Контрольные вопросы

  1. Назначение и области применения каналов?

  2. Для чего применяются анонимные каналы?

  3. Для чего применяются именованные каналы?

  4. Какие ОС поддерживают каналы?

  5. Можно ли использовать каналы в гетерогенных системах? Для связи, например, систем, работающих под ОС Unix и Windows?

  6. Какие функции используются для открытия – закрытия канала?

  7. Для чтения и записи информации в канал?

  8. Описать последовательность работы с каналом в клиентском приложении.

  9. Какие решения можно предложить в качестве серверного приложения для каналов?

  10. Охарактеризуйте каждое решение по быстродействию, удобству использования, количеству используемой памяти.

Приложения

1.Пример многопоточного сервера

#include "stdafx.h"

#define BUFSIZE 2000 // размер буфера

#define PIPE_TIMEOUT 200 // значение тайм аута

VOID InstanceThread(LPVOID);

VOID GetAnswerToRequest(LPTSTR chReq, LPTSTR chReply, LPDWORD lcnt)

{

lstrcpy(chReply,"hi");

*lcnt = 3;

}

int xx = 0;

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

{

BOOL fConnected;

DWORD dwThreadId;

HANDLE hPipe, hThread;

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

for (;;)

{

hPipe = CreateNamedPipe(

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

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

PIPE_TYPE_MESSAGE | // канал типа оьбмена сообщениями (поток сообщений)

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

PIPE_WAIT, // режим ожидания

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

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

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

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

NULL); // без атрибутов SECURITY

if (hPipe == INVALID_HANDLE_VALUE)

{

printf("CreatePipe Error");

exit(1);

}

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

// В случае успеха возвращает не нулевое значение.

// если возвращает ноль GetLastError вернет ERROR_PIPE_CONNECTED.

fConnected = ConnectNamedPipe(hPipe, NULL) ?

TRUE : (GetLastError() == ERROR_PIPE_CONNECTED);

// функция CreateThread приведена в демонстрац. целях

// в разработке использовать beginthreadex

if (fConnected)

{

// Создание потока для данного канала.

hThread = CreateThread(

NULL, // без атрибутов SECURITY

0, // размер стека по умолчанию

(LPTHREAD_START_ROUTINE) InstanceThread, // функция потока

(LPVOID) hPipe, // параметр потока

0, // поток не приостановлен

&dwThreadId); // возвращает ID потока

if (hThread == NULL)

{

printf("CreateThread Error");

exit(1);

}

else

CloseHandle(hThread);

}

else

// Клиент не может подсоедниться - закрыть канал.

CloseHandle(hPipe);

}

return 1;

}

// функция потока

VOID InstanceThread(LPVOID lpvParam)

{

CHAR chRequest[BUFSIZE];

CHAR chReply[BUFSIZE];

DWORD cbBytesRead, cbReplyBytes, cbWritten;

BOOL fSuccess;

HANDLE hPipe;

// Параметр - дескриптор канала.

hPipe = (HANDLE) lpvParam;

while (1)

{

// Чтение клиентского запроса из канала.

fSuccess = ReadFile(

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

chRequest, // буфер для приема данных

BUFSIZE, // размер буфера

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

NULL); // не перекрывающийся ввод - вывод

if (! fSuccess || cbBytesRead == 0)

break;

GetAnswerToRequest(chRequest, chReply, &cbReplyBytes);

// chReply

// Запись ответа в канал.

fSuccess = WriteFile(

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

chReply, // буфер для записи

cbReplyBytes, // количество байт для записи

&cbWritten, // количество фактически записанных байт

NULL); // не перекрывающийся ввод - вывод

if (! fSuccess || cbReplyBytes != cbWritten) break;

}

// сброс файловых буферов на диск

// позволяет клиенту прочесть содержимое канала перед отсоединением

// После закрыть дескриптор данного экземпляра канала

FlushFileBuffers(hPipe);

DisconnectNamedPipe(hPipe);

CloseHandle(hPipe);

}

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