Добавил:
Опубликованный материал нарушает ваши авторские права? Сообщите нам.
Вуз: Предмет: Файл:
КУРСОВАЯ РАБОТА .docx
Скачиваний:
28
Добавлен:
29.09.2021
Размер:
92 Кб
Скачать
☆

1.3.Разработка и описание алгоритма работы приложения

Программа предназначена для вывод на экран информации от двух серверов.

Входной информацией являются данные, которые оператор с помощью визуальных компонентов вводит в соответствующую строку

Входная информация:

  • 1;

  • 2;

  • Е.

Выходной информацией является вывод параметров на экран консоли

Выходная информация:

  • код последней ошибки;

  • текущее положение каретки

  • полное имя модуля текущего процесса;

  • идентификаторы серверных и клиентских процессов

Рис.1. UML-диаграмма деятельности приложения

1.4.Описание cтруктуры программы.

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

Для реализации именованных каналов используются классы NamedPipeServerStream и NamedPipeClientStream.

Для создания потоков был исползован класс Thread

Для вывода информации в консоль использовался метод Console.WriteLine.

Для чтения и записи в канал были использованы классы StreamReader StreamWriter

1.5.Руководство пользователя.

Оператор запускает приложение client.exe. В открывшейся консоли для соединения с 1-ым сервером надо ввести цифру «1» и нажать «Enter», на экран будет выведена информация о коде последней ошибки, текущем положении каретки. Для продолжения нажать кнопку «Enter». Далее для соединения со 2-ым сервером надо ввести цифру «2» и нажать «Enter», на экран будет выведена информация о полном имени модуля текущего процесса, идентификаторы серверных и клиентских процессов. Для выхода ввести букву «E» из латинской раскладки и нажать «Enter».

1.6.Результаты применения программы

Рис.2.Консоль

Заключение.

  • Формализованы и уточнены данные, в результате которых был разработан алгоритм решения задачи.

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

  • Создан проект с программным кодом на языке C# с использованием метода, именованный каналы.

  • Протестирована работа программы.

Список литературы

  • Э.Таненбаум, Х.Бос. Современные операционные системы. 4-изд. – СПб.: Питер, 2015

  • В.Г.Олифер, Н.А.Олифер. Сетевые операционные системы. – СПб.: Питер, 2009

  • Марк Руссинович, Дэвид Соломон, Алекс Ионеску, Павел Йосифович. Внутреннее устройство Windows.7-е издание . - СПб.: Питер, 2018

  • http://msdn.microsoft.com

  • http://ru.wikipedia.org/wiki/Клиент-сервер

  • http://www.intuit.ru/department/internet/mwebtech/5/

Приложение №1

  • Код клиента

using System;

using System.Diagnostics;

using System.IO;

using System.IO.Pipes;

using System.Security.Principal;

using System.Text;

using System.Threading;

public class PipeClient

{

private static string strNamePipe = "testpipe";

public static void Main(string[] args)

{

/*

* Работает бесконечный цикл. Для выхода необходимо ввести символ "E". Для соединения с серверными процессами необходимо ввести номер сервера 1 или 2

*/

do

{

string q;

Console.WriteLine("Enter number of server (1, 2) to connect server or character E for exit: \n");

q = Console.ReadLine();

if (q.ToUpper().CompareTo("E") == 0)

{

return;

}

else if (q.CompareTo("1") == 0 || q.CompareTo("2") == 0)

{

// Создаем клиентское подключение к именнованому каналу. Наименвоание канала равно strNamePipe + введенный номер в переменной q

var pipeClient =

new NamedPipeClientStream(".", strNamePipe + q,

PipeDirection.InOut, PipeOptions.None,

TokenImpersonationLevel.Impersonation);

Console.WriteLine("Connecting to server...\n");

pipeClient.Connect();

// Создаем экземпляр класса для чтение из канала

StreamReader sr = new StreamReader(pipeClient);

// StreamWriter sw = new StreamWriter(pipeClient);

string temp;

Console.WriteLine("Client connected to server\n");

Console.WriteLine("There are currently {0} pipe server instances open.",

pipeClient.NumberOfServerInstances);

// Читаем все строки символов пока не будет достигнут конец потока

while ((temp = sr.ReadLine()) != null)

{

// Выводим полученную информацию

Console.WriteLine("Received from server: {0}", temp);

}

// Перед окончанием процесса чтение из потока ждем нажатия любой клавиши

Console.Write("Press Enter to continue...");

Console.ReadLine();

//

pipeClient.Dispose();

}

} while (true);

}

}

  • Код 1 сервер

using System;

using System.IO;

using System.IO.Pipes;

using System.Threading;

using System.Runtime.InteropServices;

using System.Diagnostics;

public class PipeServer

{

// Число серверных потоков

private static int numThreads = 3;

public static void Main()

{

int i;

// ServerThread();

Console.WriteLine("Waiting for client connect...\n");

// Запуск северных потоков

Thread[] servers = new Thread[numThreads];

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

{

servers[i] = new Thread(ServerThread);

servers[i].Start();

}

Thread.Sleep(250);

// Цикл проверки завершения серверных потоков

while (i > 0)

{

for (int j = 0; j < numThreads; j++)

{

if (servers[j] != null)

{

// Проеряем завершение потока в течении 250 мс, если условие истинно, то поток завершился.

if (servers[j].Join(250))

{

Console.WriteLine("Server thread[{0}] finished.", servers[j].ManagedThreadId);

servers[j] = null;

i--; // decrement the thread watch count

}

}

}

}

Console.WriteLine("\nServer threads exhausted, exiting.");

}

/*

Метод запускает серверный поток

*/

private static void ServerThread()

{

try

{

// Создаем именованный канал

NamedPipeServerStream pipeServer =

new NamedPipeServerStream("testpipe1", PipeDirection.InOut, numThreads);

int threadId = Thread.CurrentThread.ManagedThreadId;

// Создаем экземпляры для чтения из канала и записи в канал

StreamReader sr = new StreamReader(pipeServer);

StreamWriter sw = new StreamWriter(pipeServer);

do

{

try

{

// Ожидает подключения клиента

pipeServer.WaitForConnection();

// Выводим в консоль Имя клиента и номер потока сервера, к которому подключился клиент

Console.WriteLine("Client {0} connected on thread[{1}].", pipeServer.GetImpersonationUserName(), threadId);

sw.Flush();

// Выводим последнюю ошибку

int error = Marshal.GetLastWin32Error();

Console.WriteLine("Last win32 error was: " + error);

sw.WriteLine("Last win32 error was: " + error);

// Выводим позицию курсора

Console.WriteLine("Cursor position: left {0}, top {1}", Console.CursorLeft, Console.CursorTop);

sw.WriteLine("Cursor position: left {0}, top {1}", Console.CursorLeft, Console.CursorTop);

// Записывает все данные из буфера в основной поток

sw.Flush();

}

// Обработка ошибок ввода-вывода

catch (IOException e)

{

Console.WriteLine("ERROR: {0}", e.Message);

}

finally

{

if (pipeServer.IsConnected)

{

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

pipeServer.WaitForPipeDrain();

}

// Отсоединяет текущее подключение

pipeServer.Disconnect();

}

} while (true);

}

// Обработка ошибок, если произошел сбой в работе серверного потока

catch (Exception e)

{

Console.WriteLine("ERROR: {0}", e.Message);

Console.ReadLine();

}

}

}

  • Код второй сервер

using System;

using System.IO;

using System.IO.Pipes;

using System.Threading;

using System.Runtime.InteropServices;

using System.Diagnostics;

public class PipeServer

{

// Число серверных потоков

private static int numThreads = 3;

public static void Main()

{

int i;

// ServerThread();

Console.WriteLine("Waiting for client connect...\n");

// Запуск северных потоков

Thread[] servers = new Thread[numThreads];

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

{

servers[i] = new Thread(ServerThread);

servers[i].Start();

}

Thread.Sleep(250);

// Цикл проверки завершения серверных потоков

while (i > 0)

{

for (int j = 0; j < numThreads; j++)

{

if (servers[j] != null)

{

// Проеряем завершение потока в течении 250 мс, если условие истинно, то поток завершился.

if (servers[j].Join(250))

{

Console.WriteLine("Server thread[{0}] finished.", servers[j].ManagedThreadId);

servers[j] = null;

i--; // decrement the thread watch count

}

}

}

}

Console.WriteLine("\nServer threads exhausted, exiting.");

}

/*

Метод запускает серверный поток

*/

private static void ServerThread()

{

try

{

// Создаем именованный канал

NamedPipeServerStream pipeServer =

new NamedPipeServerStream("testpipe2", PipeDirection.InOut, numThreads);

int threadId = Thread.CurrentThread.ManagedThreadId;

// Создаем экземпляры для чтения из канала и записи в канал

StreamReader sr = new StreamReader(pipeServer);

StreamWriter sw = new StreamWriter(pipeServer);

do

{

try

{

// Ожидает подключения клиента

pipeServer.WaitForConnection();

// Выводим в консоль Имя клиента и номер потока сервера, к которому подключился клиент

Console.WriteLine("Client {0} connected on thread[{1}].", pipeServer.GetImpersonationUserName(), threadId);

sw.Flush();

// Выводим наименование модуля текущего процесса (сервера)

string curProc = Process.GetCurrentProcess().MainModule.ModuleName;

sw.WriteLine("CurrentProcess Modulename: {0}", curProc);

/*

* Выводим ид серверных и клиентских процессов

* Получаем список всех процессов и по имени процесса определяем интересующие нас процессы

*/

Process[] proc = Process.GetProcesses();

for (int i = 0; i < proc.Length; i++)

{

if (proc[i].ProcessName.CompareTo("srv1") == 0 || proc[i].ProcessName.CompareTo("srv2") == 0 || proc[i].ProcessName.CompareTo("client") == 0 )

{

sw.WriteLine("{0}: id = {1}", proc[i].ProcessName, proc[i].Id);

}

}

// Записывает все данные из буфера в основной поток

sw.Flush();

}

// Обработка ошибок ввода-вывода

catch (IOException e)

{

Console.WriteLine("ERROR: {0}", e.Message);

}

finally

{

if (pipeServer.IsConnected)

{

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

pipeServer.WaitForPipeDrain();

}

// Отсоединяет текущее подключение

pipeServer.Disconnect();

}

} while (true);

}

// Обработка ошибок, если произошел сбой в работе серверного потока

catch (Exception e)

{

Console.WriteLine("ERROR: {0}", e.Message);

Console.ReadLine();

}

}

}