Как написать программу для удаленного доступа к ПК

Одно из самых известных приложений по удаленному управлению компьютером — TeamViewer. Займемся разработкой своего упрощенного аналога подобной клиент-серверной системы на C++ с использованием Qt. В этот раз решим подготовительные задачи по анализу и планированию того, что у нас должно получиться.

Удаленное управление в разрезе

Удаленное управление в стиле TeamViewer можно разбить на две части: серверную и клиентскую. Серверной стороной оказывается та, которой управляют. Клиент же занимается управлением.

Для серверной части основными являются следующие функции:

  1. Захват экрана и событий мыши;
  2. Трансляция по сети видео-потока для графического отображения событий, происходящих на экране;
  3. Воспроизведение полученных от удаленного клиента действий по перемещению/щелчкам мыши и нажатию клавиш клавиатуры.

Клиентской части характерны такие функции:

  1. Прием и воспроизведение видео-потока от удаленного источника (сервера) с визуальным представлением происходящего на экране;
  2. Передача на удаленный сервер событий мыши и клавиатуры по сети.

Схематично это можно представить следующим образом:

УДАЛЕННЫЙ ДОСТУП К ПК ЧЕРЕЗ PYTHON | ЧАСТЬ 1

remote-control-client-server-thumbnail

Какие модули нам понадобятся

Нам известен необходимый функционал. Распределим его по логическим модулям, которые нам потребуется разработать:

  1. InputRecorder — модуль записи видео-потока экрана, событий мыши и клавиатуры. Он нам понадобится как на клиентской, так и на серверной стороне;
  2. InputPlayer — модуль воспроизведения событий мыши и клавиатуры. Нужен на серверной стороне;
  3. RemoteControlServer — сервер удаленного управления;
  4. RemoteControlClient — клиент удаленного управления.

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

Для реализации клиент-серверного взаимодействия я планирую использовать библиотеку LibQxt. Она достаточно проста в использовании. А от сетевой части кроме примитивной передачи сообщений в Qt-приложении нам ничего и не требуется. Поэтому идем на компромисс, и жертвуем переносимостью в пользу более простой реализации.

Выводы

Пишем шустрый Remote — Desktop клиент на C# и XNA

Привет, я покажу, как написать Remote — Desktop клиент, используя C# + XNA

На написание этой статьи меня вдохновил вот этот топик

Немного от себя

Я очень долго ждал второй части той статьи, но так и не дождался. Как утверждал автор, во второй статье должна была быть реализация передачи изображения по протоколу UDP на удалённый клиент. После я пытался сам реализовать второю часть статьи, но всегда выходило плохо. Из — за медленного рисования GDI — программа просто зависала на компьютере Core 2 Duo 2.66 GHz, Nvidia GeForce 9600 GT. Я использовал разные алгоритмы оптимизации, но это слабо помогало и тогда я решил использовать XNA.

Читайте также:
Стоимостные показатели производственной программы это

Как пользоваться NjRAT? Приколы вируса удаленного доступа

Выбор протокола передачи

Очень сильно хотелось выбрать протокол передачи TCP, с ним меньше проблем, но я выбрал UDP, потомучто все говорят, что для таких дел лучше его брать бла бла бла… Вам наверное интересно почему с UDP больше проблем? Ответ прост- UDP сообщение не может превысить размер в 65 507 байт, что очень не удобно. Наши пакеты составляют в среднем размер 130 000 байт (для экрана размером 1366×768), при попытке отправить такой пакет возникает ошибка, как показано ниже.

Решить эту проблему можно двумя путями:
1) Создать костыль
2) Создать структуру

1) Так как я ленивый, выбрал костыль. Костыль заключается в том, чтобы разбивать более большое сообщение на множество маленьких и в первом сообщении писать количество кусков которое будет отправляться. Костылём я назвал, потомучто, потеряв первое сообщение, программа полетит к чертям не сможет нормально склеить изображение (она не будет знать на сколько частей разбито изображение).

2) Можно разбивать экран на множество кусочков и запоминать их координаты. Всё это надо будет хранить в структуре, что очень удобно, кстати, этот алгоритм поможет в будущем сделать оптимизацию.

Практика

Начну с простого. С отправителя. Отправлять мы будем скриншоты нашего экрана на удалённый компьютер. Я написал функцию для загрузки данных и инициализации некоторых переменных.

Точкой запуска будет наша функция Run()

public void Run() < Load(); // Загружаем данные и получаем размер экрана udpClient = new UdpClient(); Bitmap BackGround = new Bitmap(width, height); Graphics graphics = Graphics.FromImage(BackGround); while (true) < // Получаем снимок экрана graphics.CopyFromScreen(0, 0, 0, 0, new Size(width, height)); // Получаем изображение в виде массива байтов byte [] bytes = ConvertToByte(BackGround); Listlst = CutMsg(bytes); for (int i = 0; i < lst.Count; i++) < // Отправляем картинку клиенту udpClient.Send(lst[i], lst[i].Length, ipEndPoint); >> >

Сначала загружаются данные Load(), после происходит объявление переменных и зацикливание. В цикле мы получаем изображение экрана, конвертируем в массив байтов, используем мой костыль (разбиение сообщения на несколько под сообщений — CutMsg(bytes)), отправляем все пакеты.

Читайте также:
Методика лосева стирание негативных программ отзывы

В функции Load() ничего интересного не происходит.
Из файла ip.txt будут считываться две строки. Первая строка — IP адрес на который нужно отсылать данные. Вторая строка — Порт, на который будет происходить отсылка. Также там будет происходить получение длины и ширины экрана.

private byte [] ConvertToByte(Bitmap bmp) < MemoryStream memoryStream = new MemoryStream(); // Конвертируем в массив байтов с сжатием Jpeg bmp.Save(memoryStream, System.Drawing.Imaging.ImageFormat.Jpeg); return memoryStream.ToArray(); >

И самое интересное — реализация костыля.

private List CutMsg(byte[] bt) < int Lenght = bt.Length; byte[] temp; Listmsg = new List(); MemoryStream memoryStream = new MemoryStream(); // Записываем в первые 2 байта количество пакетов memoryStream.Write( BitConverter.GetBytes((short)((Lenght / 65500) + 1)), 0, 2); // Далее записываем первый пакет memoryStream.Write(bt, 0, bt.Length); memoryStream.Position = 0; // Пока все пакеты не разделили — делим КЭП while (Lenght > 0) < temp = new byte[65500]; memoryStream.Read(temp, 0, 65500); msg.Add(temp); Lenght -= 65500; >return msg; >

Я делю данные по блокам 65500 (число взял меньше, чтобы явно попасть) и записываю их в лист массивов байтов, после я возвращаю этот лист.

Код получателя

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

Асинхронное получение данных.

int countErorr = 0; private void AsyncReceiver() < IPEndPoint ep = new IPEndPoint(IPAddress.Loopback, 0); while (true) < try < MemoryStream memoryStream = new MemoryStream(); byte[] bytes = udpClient.Receive(ref ep); memoryStream.Write(bytes, 2, bytes.Length — 2); int countMsg = bytes[0] — 1; if (countMsg >10) throw new Exception(«Потеря первого пакета»); for (int i = 0; i < countMsg; i++) < byte[] bt = udpClient.Receive(ref ep); memoryStream.Write(bt, 0, bt.Length); >GetData(memoryStream.ToArray()); memoryStream.Close(); > catch < countErorr++; >> >

Снова видим зацикливание, далее получаем первый пакет, с него считываем первый байт (в этом байте записано количество будущих сообщений), если длина сообщения больше 10, то первый пакет мы явно потеряли, следовательно прибавим счётчик потерь, иначе получаем все сообщения — склеиваем в одно и вызываем событие GetData(byte []).

В GetData(byte[]) мы получаем Texture2D, конвертируя её из массива байтов.

private void Receive_GetData(byte[] Date) < BackGround = ConvertToTexture2D(Date); >private Texture2D ConvertToTexture2D(byte[] bytes) < MemoryStream memoryStream = new MemoryStream(bytes); System.Drawing.Bitmap bmp = (System.Drawing.Bitmap)System.Drawing.Bitmap.FromStream(memoryStream); // Конвертируем картинку в .png, потомучто Texture2D ест только его memoryStream = new MemoryStream(); bmp.Save(memoryStream, System.Drawing.Imaging.ImageFormat.Png); // Получаем из потока Texture2D return Texture2D.FromStream(GraphicsDevice, memoryStream); >

Читайте также:
Программа и команда разница

Весь проект вы сможете скачать в конце статьи, что так не отчаивайтесь если что — то я не написал.

Итоги и вывод

В итоге при одновременном запуске «отправителя» и «получателя» на своём компьютере происходит рекурсия и огромное количество потерь (30 — 90 потерь), при запуске «отправителя» на моём компьютере, а на компьютере родителей «получателя», потерь минимум (10 — 15 потерь). Оба компьютера (родителей и мой) соединены в одну Wi-Fi сеть с каналом 54 Мбит/с. Есть пинг (около 250 мс.) — напоминает по пингу TeamViewer. Если добавить оптимизацию и заменить костыль, то получится отличная программа для передачи изображения.

Рекурсия

Компьютер родителей (передача изображения с моего компьютера на их)

Как выглядит потеря

В следующей статье я доделаю программу, а точнее добавлю возможность удалённого управления и возможно ещё оптимизирую её.

Скачать проект
Скачать Receiver (Получает изображения)
Скачать Sender (Отправляет изображения)

Источник: habr.com

4. Работаем с функцией скриншота и выключения

Как управлять компьютером со смартфона по Wi-Fi: пишем Android-приложение на С#

Поговорим о том, как будет работать функция скриншота. Клиент запрашивает скриншот, отправляет команду в виде строки «TSC1» , на рабочей станции серверное приложение делает скриншот. Размер изображения может быть большим, поэтому мы преобразуем данные снимка экрана в пакеты байтового типа и отправляем клиентскому приложению. Когда клиент получит пакеты байтового типа, он преобразует их в исходную форму.

Добавим функцию выключения рабочей станции. Если клиент отправляет команду “SHTD3” серверному приложению, сервер выполнит функцию выключения компьютера.

5. Возвращаемся к серверному приложению

Вернемся к серверному приложению и опишем функции снимка экрана выключения рабочей станции. Откроем файл program.cs и запишем следующий код внутри цикла while , который мы реализовали ранее.

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

Ура! Всё работает. При нажатии на Sleep рабочая станция переходит в спящий режим. При нажатии на Take Screenshot через пару мгновений скриншот рабочей станции оказывается внутри клиентского приложения.

Если вы любите C#, мы также советуем вам обратить внимание на другие статьи тега C#, например, недавние:

  • Что нового будет в C# 9? Результаты исследования Proposals на GitHub
  • 10 самых популярных алгоритмов сортировки на C#
  • Исчерпывающий видеокурс: структуры данных C#

Источники

  • https://www.c-sharpcorner.com/article/xamarin-forms-controlling-your-pc-with-your-phonesusing-tcpip-protocol/
  • https://www.c-sharpcorner.com/article/xamarin-forms-controlling-your-pc-with-your-phonesusing-tcpip-protocol2/

Источник: proglib.io

Рейтинг
( Пока оценок нет )
Загрузка ...
EFT-Soft.ru