Ilya Tychinin (ejuo) wrote,
Ilya Tychinin
ejuo

Отправка сообщений между клиентом и сервером в реальном времени.

На работе почувствовал, что проект недостаточно «отзывчив».
Есть интерфейс со списком элементов. Каждый элемент характеризуется набором свойств, в т.ч. у него меняется статус. Редактирование элемента происходит в новом окне. Следовательно, отредактировав его, и переключившись на вкладку со списком, хочется видеть, что он уже изменился, стал не такой как прежде [, бросил пить, курить, и, вообще, теперь хороший человек :)].
В качестве back-end'а используется iis с asp.net mvc. Первой итерацией решил попробовать polling/long polling техники, как максимально простые, использующие стандартные асинхронные запросы к серверу.
Опирался на метод, описанный Клэем в статье WebSockets is cool, but what can you do today?
В клиенте делал $.post и прицеплял таймер:
setTimeout(function () {
            getMessages();
        }, 500)

На уровне сервера: создал асинхронный контроллер с менеджером количества запросов.
Всё бы хорошо, но где-то в таймере я ошибся. Страница периодически подвисала на 0.5-2 мин, данных из контроллера не приходило.
Вопрос этот отложил, до будущих свободных времён.
На курсе по javascript предоставилась возможность поинтересоваться у Миши. Он посоветовал веб-сокеты, которые я отмёл в начале из-за частичной поддержки в браузерах (надо включать вручную, т.к. старые версии протокола не безопасны). Привёл пример использования в Node.js (socket.io) — там это делается в несколько строк, быстро и просто. 
 Незащищённую версию протокола поддерживают все основные браузеры, что не фатально для текущих дел, поэтому всё-таки решил попробовать. Поиск выдал несколько библиотек для работы в среде .net, по гитхабу сравнил уровень поддержки, документации и дату последних коммитов. Выбор пал на SignalR. По мере доступности использует технологии: WebSockets - Server Sent Events - Forever Frame - Long polling.
Инициализация и отправка сообщений из клиента реализуется просто:
$(function () {
            // Proxy created on the fly
            var signal = $.connection.signal;
            // Call the chat method on the server
            //do something
            var msgVal = ...

            // Start the connection
            $.connection.hub.start(function () { signal.send(msgVal) });
        });

На сервере класс выглядит ещё проще:
 [HubName("signal")]
    public class signal : Hub
    {
        public void Send(string message)
        {
            //Call the addMessage method on all clients.
            Clients.addMessage(message);
        }
    }

Всё бы хорошо, но возникла необходимость создавать сообщения и на сервере. Следуя документации, в версии 0.5 это делается вызовом контекста соответствующего хаба в контроллере:
var context = GlobalHost.ConnectionManager.GetHubContext();
         context.Clients.say(message);

Но вызова не происходит. В трекере уже создана задача. Посмотрел stackoverflow, в одном из ответов, как решение, предложили вызывать статический метод из самого класса хаба, где динамически вызывается метод addMessage. После замены на context.Clients.addMessage(message), сообщения пошли:)

P.S. Вводная лекция Дэмиана, разработчика SignalR vimeo.com/43659069.
Tags: csharp, prog
Subscribe
  • Post a new comment

    Error

    Comments allowed for friends only

    Anonymous comments are disabled in this journal

    default userpic

    Your IP address will be recorded 

  • 0 comments