Определение характеристик удаленной рабочей станции

Материал из Национальной библиотеки им. Н. Э. Баумана
Последнее изменение этой страницы: 23:25, 6 декабря 2015.

Курсовое задание

Выполнили: Беляева О. В., Белякова М. А., группа ИУ7-72.

Цель работы:

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

Каждый подключенный к локальной сети клиент имеет возможность:

  • Автоматически отправить данные о своей рабочей станции в общий чат
  • Просматривать данные, посланные с других подключенных рабочих станций

Программный продукт реализован на языке высокого уровня C# в среде Visual Studio 2012.

Технические особенности клиент-серверного приложения:

  1. Разработана система авторизации на стороне клиента по его логину. При этом сервер хранит список зарегистрированных пользователей. Предусмотрена обработка ошибок по регистрации уже существующих пользователей на сервере.
  2. Шифрование переданных сообщений. В качестве алгоритма шифрования использовалось 2 алгоритма: RSA – ассиметричный алгоритм шифрования с открытым ключом и Rijndael – симметричного алгоритма шифрования. Библиотека C# предоставляет соответствующие классы для работы с этими алгоритмами RijndaelManaged и RSACryptoServiceProvider.
  3. Логирование. Для клиента и сервера реализованы собственные журналы для записи текущих событий. Каждое событие сопровождается следующей информацией: дата, время и действие.
  4. Разработан собственный протокол высокого уровня для передачи данных рабочей станции. В основе протокола лежит TCP/IP. Протокол включает в себя:
    • Метод протокола: регистрация логина клиента, запрос сообщения по номеру, отправка сообщения, запрос количества сообщений, хранящихся на сервере, запрос ключа шифрования сообщений.
    • Заголовки, позволяющие передавать дополнительную информацию (номер сообщения, тип сообщения и др.).
    • тело протокола, содержащее основную информацию
  5. Получение информации о рабочей станции из WMI-хранилища о компьютере, процессоре, ОС, Виртуальной и физической памяти, Дисках с использованием библиотеки System.Management.


Для разработки клиент-серверного приложения были использованы возможности C#, а именно:

Классы TcpListener и TcpClient библиотеки System.Net.Sockets.

Особенности программирования сервера

Ниже представлен основной класс сервера, принимающий и регистрирующий клиентов.

 
    public class Listener
    {
        public int port { get; internal set; }
        public Protocol protocol { get; internal set; }
        TcpListener listener;

        public Listener(int port, Protocol prot)
        {
            this.port = port;
            protocol = prot;
            listener = new TcpListener(IPAddress.Any, port);
            listener.Start();
        }
        // проверка на ожидающих клиентов
        public bool Ready()
        {
            return listener.Pending();
        }
        // принимает запрос на подключение
        public TcpClient Accept()
        {
            return listener.AcceptTcpClient();
        }
    }

Далее показан листинг принятия новых клиентов. После того, как клиент был принят, он передается в новый поток с точкой входа ClientThread, где создаётся новый экземпляр клиента.

            while (true)
            {
                foreach (Listener listener in listeners)
                {
                    if (listener.Ready())
                    {
                        List<object> list = new List<object>();
                        list.Add(listener.Accept());
                        list.Add(listener.protocol);

                        logger.log(DateTime.Now.ToString(MethodsAndData.DateTimeFormat) + ": New request arrived\n");
                        ThreadPool.QueueUserWorkItem(new WaitCallback(ClientThread), list);
                    }
                }
            }
        static void ClientThread(Object StateInfo)
        {
            // Просто создаем новый экземпляр класса Client и передаем ему приведенный к классу TcpClient объект StateInfo
            var list = (List<object>)StateInfo;
            new Client((TcpClient)list[0], (Protocol)list[1]);
        }

В конструкторе класса Client мы непосредственно ожидаем появления данных в потоке от клиента (TcpClient Client). Как только данные появляются, происходит их считывание. После завершения передачи данных непрерывного потока данных необходимо извлечь информацию в строку и извлечь из нее данные в соответствии с протоколом (Protocol prot). Согласно методу протокола, в функции string Methods.get.Handle(Protocol prot) выполняется соответствующее действие по запросу от клиента и возвращается ответ-строка, которая составлена в соответствии с протоколом. После чего, необходимо переконвертировать полученую строку в массив байтов и отправить обратно клиенту с помощью метода NetworkStream.Write(byte[], int, int). Соответствующий код конструктора представлен ниже:

       public Client(TcpClient Client, Protocol prot)
        {
            this.prot = prot;
            string Request = "";
            byte[] Buffer = new byte[1024];
            int Count;
            // Читаем из потока клиента до тех пор, пока от него поступают данные
            while ((Count = Client.GetStream().Read(Buffer, 0, Buffer.Length)) != 0)
            {
                Request += ByteArray.GetString(Buffer, 0, Count);                
   // Запрос должен обрываться последовательностью \r\n\r\n
                // Либо обрываем прием данных сами, если длина строки Request превышает                    предел
                if (Request.IndexOf("\r\n\r\n") >= 0 || Request.Length > maxRequestLength)
                {
                    break;
                }
                if (Client.Available <= 0)
                    break;
            }

            prot.Parse(Request);

            string response = Methods.get.Handle(prot);

            byte[] res = ByteArray.GetBytes(response);
            Client.GetStream().Write(res, 0, res.Length);

            Client.Close();
        }

Особенности программирования клиента

Часть методов основного класса клиента представлена ниже. Для соединения с сервером используется функция Connect(host, port). Для передачи запросов необходимо открыть поток, передающий последовательность байтов.

        public void OpenStream()
        {
                client = new TcpClient();
                client.Connect(host, port);
                s = client.GetStream();
        }

Процесс записи данных в поток NetworkStream выполняется так же как и для сервера. Для передачи информации через него первым делом необходимо переконвертировать информацию в массив байтов.

        public void Write(string mes)
        {
            s.Write(ByteArray.GetBytes(mes), 0, mes.Length);
        }

        public string Read()
        {
            string str = "";
            byte[] Buffer = new byte[4096];
            int Count;
            while ((Count = s.Read(Buffer, 0, Buffer.Length)) != 0)
            {
                str += ByteArray.GetString(Buffer, 0, Count);
                // Запрос должен обрываться последовательностью \r\n\r\n
                // Либо обрываем прием данных сами, если длина строки Request превышает предел
                if (str.IndexOf("\r\n\r\n") >= 0 || str.Length > 1024 * 1024 * 10)
                {
                    break;
                }
// значение, указывающее количество полученных из сети и доступных для чтения данных.
                if (client.Available <= 0)
                    break;
            }

            return str;
        }
	 // закрытие подключения
        public void CloseStream()
        {
            client.Close();
        }
        /* входные параметры: method - метод протокола,
                      type - дополнительная информация, 
                      body - основная инф-я (сообщение) */
        public string RequestResponse(string method, string type, string body)
        {
            try{
            OpenStream();
            prot.methodName = method;
            prot.body = body;
            prot.headers = StringToHeaders(type);
            Write(prot.toProt());
            string response = Read();
            CloseStream();
            prot.Parse(response);
            return prot.body;
              }
            catch (Exception ex)
            {
                MessageBox.Show(ex.Message.ToString());
                return "";
            }
        }

Настройка сетевого адаптера в Windows Vista/7/8

  • Зайдите в меню Пуск > Панель управления > Центр управления сетями и общим доступом и щелкните по ссылке Подключение по локальной сети.
  • В открывшемся окне нажмите кнопку Свойства.
  • Выберите пункт Протокол Интернета версии 4 (TCP/IPv4) и нажмите кнопку Свойства.
  • В окне свойств протокола выберите Получить IP-адрес автоматически для автоматического назначения динамического IP-адреса от интернет-центра (на котором включен DHCP-сервер) на сетевой адаптер компьютера.
  • Если необходимо, вы можете указать статический IP-адрес вручную (выберите Использовать следующий IP-адрес и в полях IP-адрес и Маска подсети укажите соответственно IP-адрес и маску). (IP-адреса рабочих станций должны принадлежать к одной подсети)

Порядок работы с программным комплексом

  1. Запуск сервера:
  2. Каждому клиенту необходимо подключиться к выбранному серверу – пройти авторизацию:
  3. Отправка данных в общий чат производится автоматически при нажатии кнопки «Послать данные рабочей станции», после чего переданная информация записывается на сервере:
  4. Просмотр всех отправленных в общий чат данных производится в окне: (Клиент запрашивает данные, полученный сервером от всех клиентов.)

Ссылки

  1. MSDN SystemNetSocket
  2. Алгоритм многопоточного клиент-сервера
  3. Клиент-серверное приложение на потоковом сокете TCP
  4. WMI-хранилище C# MSDN System.Management
  5. MSDN System.Security.Cryptography (алгоритмы RSACryptoServiceProvider и RijndaelManaged)