Silverlight: Реализация VNC клиента

вторник, 23 марта 2010, Евгений Жарков

image[3]

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

Наконец, после первого проблеска Silverlight 4.0, я решил достань запылившийся код и толкнуть это дело в народ и все благодаря новому функционалу – запуск приложений вне браузера (OOB). Теперь я мог расслабиться с сокетами, приложение устанавливается как полностью доверительное и я волен работать с любым сервисом на основе сокетов и больше не нужно иметь в наличии policy-сервер.

Итак представляю вашему вниманию SilverVNC, базовую реализацию Remote Framebuffer протокола (RFB), со спецификациями вы можете ознакомиться на сайте RealVNC. Реализацию протокола производил с помощью последней верси UltraVNC.

Как я уже сказал, реализация базовая. В отличии от коммерческой версии, я поддерживаю только RAW-кодирование и не использую компрессию какого-либо типа.. Потому что обработка тяжелых сокет-связей с помощью асинхронной модели в silverlight - своего рода хождение по лезвию, вроде просто, а в реальности все гораздо серьезней и сложнее. Так что я решил предоставить пользователю простой пример, как оно работает.

Принцип работы

Ядром примера, является класс RfbClient, который инкапсулирует всю нужную логику для связи с сервером, декодирования данных и отправки событий пользовательскому интерфейсу. Класс состоит из метродов, которые принимают и отправляют данные в сокет. Не буду углубляться в недра класса, потому что описание спецификации RFB-протокола не входит в данную статью. Вам нужно только знать, что благодаря OOB приложение может открывать сокет на любом порту без никаких разрешений.

Главная страница приложения  использует RfbClient для подключения к VNC сервера и тянет с него данные и декодирует. Каждый раз, когда RfbClient что-то получает, то вызывает два типа события:

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

FramBufferUpdate – сервер определил изменения на экране, вырезал измененный участок и передал на сервер. Обработчик события рассчитал позицию квадрата на отрисовываемой области и вывел его на экран.

Вот пример обработки этих событий:

 

   1: void Client_ResizeFrameBuffer(object sender, EventArgs e)
   2: {
   3:     this.MakeWindowProportional(this.Client.Server.Width, this.Client.Server.Height);
   4:     this.BitMap = new WriteableBitmap(this.Client.Server.Width, this.Client.Server.Height);
   5:     this.vnc.Source = this.BitMap;
   6: }
   7:  
   8: private void MakeWindowProportional(double width, double height)
   9: {
  10:     double proportion = width / height;
  11:     Application.Current.MainWindow.Height = Application.Current.MainWindow.Width / proportion;
  12:     Application.Current.MainWindow.Activate();
  13: }
  14:  
  15: private void Client_FrameBufferUpdate(object sender, FrameBufferUpdateEventArgs e)
  16: {
  17:     Rect rect = e.Rectangle;
  18:  
  19:     int x = 0;
  20:     int y = 0;
  21:  
  22:     foreach (uint color in e.Colors)
  23:     {
  24:         this.BitMap.Pixels[
  25:             (y + (int)rect.Y) *
  26:             this.Client.Server.Width +
  27:             (x + (int)rect.X)] = (int)color;
  28:  
  29:         if (++x == rect.Width)
  30:         {
  31:             x = 0;
  32:             y++;
  33:         }
  34:     }
  35:  
  36:     this.BitMap.Invalidate();
  37: }
Что дальше?

Я думаю, вскоре я добавлю еще некоторый функционал и улучшения. Прежде всего я размышляю над написанием алгоритма записи в буфер, он должен быть более эффективным, чем код показанный выше. Мой идея – реализовать MediaStreamSource, для предоставления видео потока, который можно подключить к MediaElement. Это должно быть лучше не только с точки зрения производительности, но и простоты использования для разработчиков, которым нужно добавить просмоторщик удаленного рабочего стола в свои приложения.

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

А пока, прошу попробовать текущее приложения и слышать отзывы.

Исходный код : http://www.silverlightplayground.org/assets/sources/SilverlightPlayground.RFB.zip
Видео: http://www.silverlightplayground.org/assets/video/SilverVNC.wmv
RFB спецификации: The RFB Protocol

Источник - Silverlight Playground


Ищите нас в интернетах!

Комментарии

Свежие вакансии