Скриншоты выполнения программ

МОСКОВСКИЙ ТЕХНОЛОГИЧЕСКИЙ УНИВЕРСИТЕТ

(МИРЭА, МГУПИ, МИТХТ)»

Институт комплексной безопасности и специального приборостроения

КБ-3 «Управление и моделирование систем»

КУРСОВАЯ РАБОТА

По дисциплине

«Проектирование и архитектура программных систем»

Тема курсового проекта (работы):

".NET Remoting"

Студент группы ВПБВ-01-14Храбров И.С._

(Ф.И.О.) студента

 

Руководитель курсового _________________ _____________

проекта (работы) должность, звание, ученая степень (Ф.И.О.)

Рецензент (при наличии) _________________ _____________

должность, звание, ученая степень (Ф.И.О.)

 

Работа представлена к защите «__» __________201_г. _____________

(подпись студента)

Допущен к защите «__» __________201_г. _____________

(подпись руководителя)

 

Москва, 2016

 

МИНОБРНАУКИ РОССИИ

Федеральное государственное бюджетное образовательное учреждение

высшего профессионального образования

 

МОСКОВСКИЙ ТЕХНОЛОГИЧЕСКИЙ УНИВЕРСИТЕТ

(МИРЭА, МГУПИ, МИТХТ)»

Институт комплексной безопасности и специального приборостроения

КБ-3 «Управление и моделирование систем»

Утверждаю

Зам. Заведующего

Кафедрой __________________

«__» _______201_г.

ЗАДАНИЕ

на выполнение курсового проекта (работы)

по дисциплине«Проектирование и архитектура программных систем»

студент __________Храбров Игорь Сергеевич Группа ВПБВ-01-14

1. Тема:«.NET Remoting»

2. Исходные данные:

1) Предметная область: архитектура программных систем

2) Примерные отношения предметной области: удаленное администрирование, клиент-серверные технологии.

3. Перечень вопросов, подлежащих разработке, и обязательного графического материала:

В рамках курсовой работы необходимо разработать клиент-серверное приложение, серверная часть которого реализована на C#, представляющая собой модель предметной области. На стороне сервера реализовать и использовать при демонстрации приложения следующие компоненты:

1) HTTP-подключение

2) Объект класса TcpListener

3) Прием команд с клиентской стороны

4) Выполнение команд в консоли операционной системы с последующей выдачей результата приложению-клиенту

4. Срок представления к защите курсового проекта(работы) до: «__»_________2016г.

 

Задание на курсовой

проект (работу) выдал «__»________201_г. _______________ ________________

Подпись руководителя Ф.И.О. руководителя проекта

проекта проекта

Задание на курсовой

проект (работу) получил «__»________201_г. _______________ ________________

Подпись студента- Ф.И.О. студента-исполнителя

исполнителя- проекта проекта

МИНОБРНАУКИ РОССИИ

Федеральное государственное бюджетное образовательное учреждение

высшего профессионального образования

 

МОСКОВСКИЙ ТЕХНОЛОГИЧЕСКИЙ УНИВЕРСИТЕТ

(МИРЭА, МГУПИ, МИТХТ)»

Институт комплексной безопасности и специального приборостроения

КБ-3 «Управление и моделирование систем»

 

РЕЦЕНЗИЯ НА

КУРСОВУЮ РАБОТУ

студента Храброва Игоря Сергеевича

группы ВПБВ-01-14, __ курса, выполненную

на тему: «.NET Remoting»

 

Пояснительная записка.

_______________________________________________________________________________________________________________________________________________________________________________________________________________________________________________________________

Наличие:

титульный лист

задание

теоретическая часть

исходные коды, листинг программ

скриншоты приложения

заключение

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

Серверная часть.

_______________________________________________________________________________________________________________________________________________________________________________________________________________________________________________________________

Клиентская часть.

_______________________________________________________________________________________________________________________________________________________________________________________________________________________________________________________________

Общая оценка работы.

_______________________________________________________________________________________________________________________________________________________________________________________________________________________________________________________________

 

«__»________201_г. _______________ ________________

(Ф.И.О.) (Подпись)

Теоретическая часть

.NET Remoting — компонент, созданный компанией Microsoft. API для межпроцессного взаимодействия. Реализация от Microsoft протокола SOAP (веб-сервисы). Выпущен в 2002 году вместе с версией 1.0 пакета .NET Framework. Это одна из серии технологий от Microsoft, начатой в 1990 году первой версией OLE для 16-разрядной Windows. Промежуточными шагами в разработке подобных технологий были COM, выпущенная в 1993 году и доработанная в 1995 году под названием COM-95, DCOM, выпущенная в 1997 году (и переименованная в ActiveX), и COM+ с её Microsoft Transaction Server (MTS), выпущенная в 2000 году. В данный момент на смену .NET Remoting пришёл WCF, являющийся частью .NET Framework 3.0.

Так же, как и все члены данного семейства и подобные технологии, например CORBA и RMI, функция .NET Remoting заключается в следующем: при поддержке со стороны инфраструктуры .NET Remoting, клиентский процесс отправляет сообщение серверному процессу и получает ответ.

.NET Remoting позволяет приложению создать объект (именуемый remotable object) доступный в рамках remoting boundaries и расположенный в домене приложения внутри одного процесса, другом процессе, исполняющемся на этом компьютере, или даже на другом компьютере, соединённом сетью. Процесс .NET Remoting содержит приёмник запросов к объекту в домене серверного приложения. На стороне клиента любые запросы к удалённому объекту направляются средой выполнения .NET Remoting через объекты Channel, являющиеся обёрткой для средств транспортного уровня, таких как потоки TCP, потоки HTTP и именованные каналы. В результате, запросы к удаленным объектам для клиентского кода ничем не отличаются от локальных вызовов, а созданием экземпляра нужного Channel-объекта, приложение .NET Remoting можно без перекомпиляции перевести на другой коммуникационный протокол. Среда выполнения сама по себе выполняет этапы сериализации и маршалинга объектов в среде между клиентским и серверным доменами приложения.

.NET Remoting делает ссылку на удалённый (remotable) объект доступной клиентскому приложению, которое затем направляет запросы к экземпляру удалённого объекта так, как если бы это был локальный объект. Однако, фактическое исполнение кода происходит на серверной стороне. Удалённый объект имеет идентификаторы в форме URL активации. В зависимости от конфигурации серверного процесса, экземпляр удаленного объекта создаётся при подключении по данным URL, в момент создания ссылки на удалённый объект или в момент первого обращения к удалённому объекту. Прослушивающий приёмник (listener) для объекта создаётся исполняющей средой .NET Remoting в момент, когда сервер регистрирует канал, который будет использоваться для подключения к удалённому объекту. На клиентской стороне инфраструктура .NET Remoting создаёт объект-заместитель (proxy), который является псевдоэкземпляром замещаемого объекта. Он не реализует функциональность удалённого объекта, но предоставляет похожий интерфейс, перенаправляя все запросы серверному объекту и возвращая результаты от него клиенту . Как следствие, инфраструктуре .NET Remoting для создания заместителя нужно обладать метаданными, описывающими публичный интерфейс удалённого объекта. Это можно обеспечить статическим связыванием со сборкой, содержащей метаданные, во время компиляции или динамическим получением метаданных в виде WSDL или проприетарного формата, разработанного фирмой Microsoft.

 

В процессе выполнения запросов любые вызовы методов, направленные объекту, включая идентификатор метода и любые передаваемые параметры, сериализуются в байтовый поток и передаются посредством канала связи, реализованного для конкретного протокола, принимающему прокси-объекту на серверной стороне («маршализируются»). Передача происходит путём записи данных в транспортный ввод канала. На серверной стороне прокси читает поток данных из вывода канала и выполняет вызов удалённого компонента от лица клиента. Результаты сериализуются и передаются через канал клиенту, где прокси читает результат и передаёт его вызывающему приложению.

 

Если удалённому объекту нужно обеспечить обратный вызов (callback) клиентскому объекту, клиентский объект обратного вызова должен быть помечен как remotable, а инфраструктура .NET Remoting должна быть сконфигурирована на создание прослушивателя для него. Сервер может подключиться к нему по другому каналу, или по уже существующему, если соединение, на котором он основан, поддерживает двунаправленный обмен данными. Канал может быть составлен из нескольких канальных объектов, возможно, даже с разными транспортными механизмами. Таким образом, система, основанная на .NET Remoting, может состоять из нескольких подсистем, связанных подключёнными друг к другу гетерогенными сетями, включая Интернет.

Исходные коды

Серверная часть.

using System;

using System.Collections.Generic;

using System.Linq;

using System.Text;

using System.Threading.Tasks;

using System.Threading;

using System.Net;

using System.Net.Sockets;

using System.Net.Security;

using System.Diagnostics;

using System.Security;

using System.ComponentModel;

using System.Security.Principal;

using System.Security.Authentication;

 

 

namespace Volovich_1_lab_server

{

class Program

{

static void Main(string[] args)

{

 

int counter = 0;

string ipStr = "127.0.0.1";

int MaxThreadsCount = Environment.ProcessorCount * 4;

ThreadPool.SetMaxThreads(MaxThreadsCount, MaxThreadsCount);

ThreadPool.SetMinThreads(2, 2);

IPAddress ipAddr = IPAddress.Parse(ipStr);

Int32 port = 13234;

IPEndPoint endPoint = new IPEndPoint(ipAddr, port);

TcpListener tcpServer = new TcpListener(endPoint);

 

try {

tcpServer.Start();

while (true)

{

Console.Write("\nWaiting for a connection... ");

ThreadPool.QueueUserWorkItem(NewClient, tcpServer.AcceptTcpClient());

counter++;

Console.Write("\nConnection №" + counter.ToString() + "!");

 

}

}

catch(Exception ex)

{

Console.WriteLine("Не удалось запустить сервер: "+ex.Message);

}

tcpServer.Stop();

Console.ReadLine();

}

static void NewClient(object client_obj)

{

TcpClient client = client_obj as TcpClient;

bool auth = false;

string domain = "", login = "", password = "";

try

{

NetworkStream tcpStream = client.GetStream();

// Аутентификация клиента

WindowsIdentity wi = null;

byte[] bt = new byte[2048];

NegotiateStream secStream = new NegotiateStream(client.GetStream());

NetworkCredential nc = (NetworkCredential)CredentialCache.DefaultCredentials;

secStream.AuthenticateAsServer(nc, ProtectionLevel.None, TokenImpersonationLevel.Impersonation);

wi = (WindowsIdentity)secStream.RemoteIdentity;

IIdentity id = secStream.RemoteIdentity;

string username = id.Name;

if (wi.IsAuthenticated)

{

username = wi.Name;

Console.WriteLine("Клиент аутентифицирован");

int bytesRead = 0;

byte[] authByte;

authByte = new byte[client.ReceiveBufferSize];

bytesRead = secStream.Read(authByte, 0, client.ReceiveBufferSize);

domain = Encoding.Unicode.GetString(authByte).Replace("\0","").Trim();

Console.WriteLine("Клиент-домен:" + domain);

byte[] sendByte2 = Encoding.Unicode.GetBytes("OK\n");

secStream.Write(sendByte2, 0, sendByte2.Length);

Array.Clear(authByte, 0, authByte.Length);

authByte = new byte[0];

authByte = new byte[client.ReceiveBufferSize];

bytesRead = secStream.Read(authByte, 0, client.ReceiveBufferSize);

login = Encoding.Unicode.GetString(authByte).Replace("\0", "").Trim();

Console.WriteLine("Клиент-логин:" + login);

sendByte2 = Encoding.Unicode.GetBytes("OK\n");

secStream.Write(sendByte2, 0, sendByte2.Length);

Array.Clear(authByte, 0, authByte.Length);

authByte = new byte[0];

authByte = new byte[client.ReceiveBufferSize];

bytesRead = secStream.Read(authByte, 0, client.ReceiveBufferSize);

password = Encoding.Unicode.GetString(authByte).Replace("\0", "").Trim();

Console.WriteLine("Клиент-пароль:" + password);

sendByte2 = Encoding.Unicode.GetBytes("OK\n");

secStream.Write(sendByte2, 0, sendByte2.Length);

}

else

{

Console.WriteLine("Клиент не аутентифицирован");

return;

}

bool nslookup = false;

System.Diagnostics.Process proc = new System.Diagnostics.Process();

try

{

proc.StartInfo.FileName = @"C:\Windows\System32\cmd.exe";

proc.StartInfo.RedirectStandardOutput = true;

proc.StartInfo.RedirectStandardInput = true;

proc.StartInfo.RedirectStandardError = true;

proc.StartInfo.UseShellExecute = false;

proc.StartInfo.CreateNoWindow = true;

proc.StartInfo.WorkingDirectory = @"C:\Windows\System32";

proc.StartInfo.Domain = domain;

proc.StartInfo.UserName = login;

SecureString pass = new SecureString();

for (int j = 0; j < password.Length; j++)

pass.AppendChar(password[j]);

proc.StartInfo.Password = pass;

proc.Start();

byte[] sendByte = Encoding.Unicode.GetBytes("success auth");

secStream.Write(sendByte, 0, sendByte.Length);

Console.WriteLine("Успешный запуск консоли. Пользователь:"+login);

}

catch (Exception ex)

{

Console.WriteLine("Ошибка запуска консоли:" + ex.Message);

byte[] sendByte = Encoding.Unicode.GetBytes(ex.Message);

secStream.Write(sendByte, 0, sendByte.Length);

client.Close();

return;

}

Thread writer = new Thread(func);

MyClass myc = new MyClass();

myc.proc = proc;

myc.stream = secStream;

writer.Start(myc);

Thread writerErr = new Thread(funcErr);

MyClass mycErr = new MyClass();

mycErr.proc = proc;

mycErr.stream = secStream;

writerErr.Start(mycErr);

while (true)

{

string Data;

byte[] recievByte;

int bytesRead;

recievByte = new byte[client.ReceiveBufferSize];

Array.Clear(recievByte, 0, recievByte.Length);

bytesRead = secStream.Read(recievByte, 0, client.ReceiveBufferSize);

Data = Encoding.Unicode.GetString(recievByte);

Data = Data.Trim();

Data = Data.Replace("\0", "");

Data = Data.ToLower();

Console.WriteLine("\nКоманда: " + Data + "\n");

proc.StandardInput.WriteLine(Data);

proc.StandardInput.Flush();

if (Data.Split(' ')[0] == "exit")

{

Console.WriteLine("Введена команда exit");

if (proc.HasExited)

{

byte[] sendByte2 = Encoding.Unicode.GetBytes("\nexit\n");

secStream.Write(sendByte2, 0, sendByte2.Length);

break;

}

}

}

proc.WaitForExit();

if (tcpStream!=null)

tcpStream.Close();

if (secStream != null)

secStream.Close();

}

catch (Exception ex)

{

Console.WriteLine("Ошибка подключения клиента: " + ex.Message);

}

Console.WriteLine("вышли");

client.Close();

}

 

private static void func(object obj)

{

MyClass myc = (MyClass)obj;

Process process = (Process)myc.proc;

NegotiateStream stream = (NegotiateStream)myc.stream;

string outputString = "";

while (!(process.StandardOutput.EndOfStream))

{

if (process.HasExited)

{

process.Close();

stream.Close();

break;

}

outputString = process.StandardOutput.ReadLine()+"\n";

Console.WriteLine(outputString);

byte[] sendByte2 = Encoding.Unicode.GetBytes(outputString);

try

{

stream.Write(sendByte2, 0, sendByte2.Length);

}

catch (Exception ex)

{

Console.WriteLine("func exception: "+ex.Message);

process.Close();

stream.Close();

break;

}

}

}

private static void funcErr(object obj)

{

MyClass myc = (MyClass)obj;

Process process = (Process)myc.proc;

NegotiateStream stream = (NegotiateStream)myc.stream;

string outputString = "";

while (!(process.StandardError.EndOfStream))

{

 

if (process.HasExited)

{

process.Close();

stream.Close();

break;

}

outputString = process.StandardError.ReadLine() + "\n";

Console.WriteLine(outputString);

byte[] sendByte2 = Encoding.Unicode.GetBytes(outputString);

try

{

stream.Write(sendByte2, 0, sendByte2.Length);

}

catch (Exception ex)

{

Console.WriteLine("func exception: " + ex.Message);

process.Close();

stream.Close();

break;

}

}

 

}

private class MyClass

{

public Process proc;

public NegotiateStream stream;

public MyClass()

{

proc = null;

stream = null;

}

}

}

}


 

Клиентская часть.

using System;

using System.Collections.Generic;

using System.Text;

using System.Net.Sockets;

using System.Net;

using System.Threading;

using System.Security.Principal;

using System.Security;

using System.Net.Security;

using System.Security.Authentication;

using System.Security.Principal;

 

namespace ClientConsole

{

class Program

{

private static TcpClient client;

private static NegotiateStream secStream;

private static bool auth = false;

private static string domain = "";

private static string login = "";

private static string password = "";

static void Main(string[] args)

{

string command="";

Console.WriteLine("Начинайте вводить команды");

while (true)

{

Console.Write("->:");

if ((command = Console.ReadLine()) == "disconnect") {

Console.WriteLine("Разлогинились.");

if (client.Connected)

client.Close();

if (secStream != null)

secStream.Close();

auth = false;

continue; }

 

if (command == "q") break;

if (auth == false)

{

string ipStr = "172.22.121.196";

Console.Write("IP-адрес:");

ipStr = Console.ReadLine();

if(ipStr!=""){

Console.WriteLine("Будет использован IP-адресс:" + ipStr);

 

}else{

ipStr = "172.22.121.196";

Console.WriteLine("Будет использован локальный IP-адресс:"+ipStr);

}

do{

Console.Write("Домен:");

domain = Console.ReadLine();

} while (domain == "");

do{

Console.Write("Логин:");

login = Console.ReadLine();

} while (login == "");

do

{

Console.Write("Пароль:");

password = Console.ReadLine();

} while (password == "");

client = new TcpClient();

try {

Console.WriteLine("Будет использован IP-адресс:" + ipStr);

client.Connect(ipStr, 13234);

 

}

catch (Exception exx){

Console.WriteLine("Server exceprion: " + exx.Message);

continue;

}

try{

 

secStream = new NegotiateStream(client.GetStream());

NetworkCredential cred = (NetworkCredential)CredentialCache.DefaultCredentials;

secStream.WriteTimeout = 3000;

secStream.ReadTimeout = 3000;

try{

secStream.AuthenticateAsClient(cred, "user-pc", ProtectionLevel.None, TokenImpersonationLevel.Impersonation); // Если аутентификация не пройдена, то выбрасывается исключение

}

catch (System.IO.IOException iex){

Console.WriteLine("Аутентификация не пройдена. "+iex.Message);

continue;

 

}

Console.WriteLine("Аутентификация пройдена");

byte[] sendByte = Encoding.Unicode.GetBytes(domain);

secStream.Write(sendByte, 0, sendByte.Length);

byte[] recievByte = new byte[client.ReceiveBufferSize];

int bread = secStream.Read(recievByte, 0, client.ReceiveBufferSize);

Array.Clear(sendByte, 0, sendByte.Length);

sendByte = new byte[0];

Array.Clear(recievByte, 0, recievByte.Length);

recievByte = new byte[0];

sendByte = Encoding.Unicode.GetBytes(login);

secStream.Write(sendByte, 0, sendByte.Length);

recievByte = new byte[client.ReceiveBufferSize];

bread = secStream.Read(recievByte, 0, client.ReceiveBufferSize);

Array.Clear(sendByte, 0, sendByte.Length);

sendByte = new byte[0];

Array.Clear(recievByte, 0, recievByte.Length);

recievByte = new byte[0];

sendByte = Encoding.Unicode.GetBytes(password);

secStream.Write(sendByte, 0, sendByte.Length);

recievByte = new byte[client.ReceiveBufferSize];

bread = secStream.Read(recievByte, 0, client.ReceiveBufferSize);

Array.Clear(recievByte, 0, recievByte.Length);

recievByte = new byte[0];

recievByte = new byte[client.ReceiveBufferSize];

bread = secStream.Read(recievByte, 0, client.ReceiveBufferSize);

string result = Encoding.Unicode.GetString(recievByte).Replace("\0","").Trim();

if (result == "success auth"){

Console.WriteLine("Успешная авторизация. Запуск удаленной консоли.");

auth = true;}

else{

Console.WriteLine("Ошибка авторизации." + result);

continue;}

}

catch (InvalidCredentialException) // Аутентификация на сервере не пройдена

{

Console.WriteLine("Аутентификация на сервере не пройдена");

}

}

else

if (auth)

{

try

{

if (command != "")

{

byte[] sendByte = Encoding.Unicode.GetBytes(command);

secStream.Write(sendByte, 0, sendByte.Length);

DateTime dt = DateTime.Now;

Console.WriteLine("");

Console.WriteLine("Время: " + dt.ToString() + " КОМАНДА:" + command);

Thread.Sleep(2000);

}

int bytesRead = 0;

while (true){

Thread.Sleep(1500);

byte[] recievByte = new byte[client.ReceiveBufferSize];

try{

if ((bytesRead = secStream.Read(recievByte, 0, client.ReceiveBufferSize)) <= 0){ break;}

string Data = "";

Data = Encoding.Unicode.GetString(recievByte).Replace("\0","").Trim();

string[] values = Data.Split('\n');

foreach (string value in values)

{

if (value.Trim() == ""){

Console.WriteLine("");

continue;

}

if (value.ToLower() == "exit") {

if (client.Connected) {

client.Close();

auth = false;

break;

}

 

}

Console.WriteLine(value.Trim());

}

}

catch (Exception tEx){break;}

}

 

}

catch (Exception ex)

{

Console.WriteLine("Exceprion2: " + ex.Message);

}

 

}

if (!client.Connected && !auth)

{

Console.WriteLine("Отключились.");

break;

}

}

Console.WriteLine("Завершение программы.");

Console.ReadKey();

}

}

}


 

Скриншоты выполнения программ

Рисунок 1. Клиентское приложение

Рисунок 2. Серверная часть приложения

Рисунок 3. Совместное использование клиент-серверного приложение.

Команда nslookup


 

Заключение

.NET-Remoting – мощный инструмент, позволяющий взаимодействовать различным системам удаленно. Благодаря нему можно обеспечить передачу объектов от одного приложения, выполненного на удаленной машине, к серверной машине, на которой установлено соответствующее приложение.


 

Список используемой литературы

1. https://ru.wikipedia.org/wiki/.NET_Remoting

2. https://www.bytemag.ru/articles/detail.php?ID=8891

3. https://habrahabr.ru/post/124491/

4. Microsoft .NET Remoting, John Willey, 2003, ISBN 9780735617780