При создании веб-приложений вы часто сталкиваетесь с тем, что HTTP, основа Интернета, является протоколом запроса / ответа. Клиент выдает запрос, сервер обрабатывает этот запрос и отправляет ответ. Все время, без связи между первым запросом и последующими запросами. Кроме того, поскольку он основан на запросах, невозможно отправить сообщения с сервера на клиент без предварительного создания запроса клиентом.
Сегодня пользователи ожидают, что в их проектах, извините, за «опыт», доступна форма «реального времени». Такие вопросы, как «Я хочу, чтобы этот тикер обновлялся при каждом изменении цены» или «Я хочу просматривать GPS-местоположения моих транспортных средств в режиме реального времени на этой карте». Или даже лучше: для совместной работы людей часто требуются живые уведомления и изменения в браузере, так что всякий раз, когда пользователь запускает задачу или событие, другие пользователи, сотрудничающие немедленно, получают уведомление. Подумайте о таблицах Google, где вы можете работать вместе. Подумайте, чат в Facebook. Подумайте в Твиттере, где автоматически появляются новые сообщения. Подумайте о своих приложениях, посыпав соусом в реальном времени.
Как бы вы это реализовали?
Но что, если сервер хочет общаться с клиентом?
На протяжении многих лет веб-разработчики очень изобретательно работали над характером запросов / ответов в Интернете. На разных платформах используются два метода, которые обеспечивают относительно легкий обход проблемы «парадигмы HTTP», когда клиент инициирует любое соединение: простой опрос с использованием Ajax и один из вариантов — длинный опрос.
Простой Ajax-опрос, ну, в общем-то, прост: клиент «опрашивает» сервер с помощью Ajax-запроса, на который сервер отвечает, если есть данные. Клиент ждет некоторое время и снова проходит этот процесс. Схематически это будет следующим:
Проблема в том, что сервер все еще зависит от клиента, инициирующего соединение. Всякий раз, когда в течение интервала опроса сервер имеет данные для клиента, эти данные могут быть отправлены клиенту только при следующем цикле опроса. Это, вероятно, не проблема, когда интервал опроса находится в диапазоне 100 мс, за исключением того факта, что вы будете молотить ваши серверы при этом. С того момента, как ваш интервал опроса увеличивается до 2 или даже 30 секунд, вы теряете часть идеи общения в режиме реального времени.
Эта проблема была решена с помощью метода, называемого «длинный опрос». Идея состоит в том, что клиент открывает соединение с сервером на основе Ajax, сервер не отвечает, пока не получит данные. У клиента просто есть ложное ощущение, что запрос занимает некоторое время, и в конечном итоге некоторые данные будут возвращаться с сервера. Всякий раз, когда данные возвращаются, клиент немедленно снова открывает соединение с «длинным опросом». Схематично:
Интервал опроса отсутствует: до тех пор, пока соединение открыто, сервер может отправлять данные обратно клиенту. Круто, верно? Не совсем … Ваши серверы не будут забиты миллиардами запросов, но для обработки запросов потребуется некоторое время («длинный опрос»). Представьте себе, что будет делать ваш пул потоков ASP.NET в таком случае … Ну, если вы не реализуете свою сторону сервера, используя IAsyncHttpHandler или подобное. В противном случае ваши серверы просто перестанут принимать запросы.
HTML5 на помощь?
Как мы уже видели, обе существующие технологии работают для симуляции полнодуплексной связи между клиентом и сервером. Однако у них обоих есть некоторые недостатки, если вы не знаете, что делаете. Кроме того, методы, описанные ранее, просто имитируют двунаправленную связь. Разве не было бы неплохо иметь решение, которое прекрасно работает и предназначено для этого? Встречайте HTML5 WebSockets .
WebSockets предлагает реальное двунаправленное TCP-соединение между клиентом и сервером. Это верно, TCP (не HTTP) соединение. Чтобы установить соединение WebSocket, клиент отправляет запрос рукопожатия WebSocket по HTTP, сервер отправляет ответ рукопожатия WebSocket с подробной информацией о том, как открыть фактическое соединение TCP. Так просто! Схематично:
К сожалению, сеть развивается не так быстро … WebSockets все еще является черновой спецификацией («CTP» или «альфа», как вы будете). Не все браузеры поддерживают их. А поскольку они используют необработанное TCP-соединение, многие прокси-серверы, используемые в компаниях, пока не поддерживают их. Мы доберемся туда, только не сегодня. Кроме того, если вы хотите использовать WebSockets с ASP.NET, вам придется использовать предварительную версию .NET 4.5.
Так что же делать в этом запутанном мире? Как достичь двунаправленной связи в реальном времени через Интернет сегодня?
СигналР на помощь!
SignalR — это «библиотека асинхронной сигнализации для ASP.NET, над которой работает Microsoft для создания многопользовательских веб-приложений в реальном времени». Позвольте мне перефразировать это: SignalR — это библиотека ASP.NET, которая использует три метода, которые я описал ранее, для создания единого взаимодействия между клиентом и сервером.
Основная идея SignalR заключается в том, что граница между клиентом и сервером должна стать легче преодолевать. Очень быстрый пример — две части кода. Клиентская сторона:
var helloConnection = $.connection.hello; helloConnection.sayHelloToMe = function (message) { alert(message); }; $.connection.hub.start(function() { helloConnection.sayHelloToAll("Hello all!"); });
На стороне сервера:
public class Hello : Hub { public void SayHelloToAll(string message) { Clients.sayHelloToMe(message); } }
Вы уже видите ссылку? Клиент JavaScript вызывает метод C # «SayHelloToAll», как если бы это была функция JavaScript. Сторона C # вызывает всех своих клиентов (имеется в виду 200 000 окон браузера, подключающихся к этой службе :-)) Метод JavaScript «sayHelloToMe», как если бы это был метод C #.
Если добавить, что поддерживаются не только клиенты JavaScript, но также Windows Phone, Silverlight и обычный .NET, это звучит интересно? Если я добавлю, что SignalR может использовать любой из трех методов, описанных ранее в этом посте, в зависимости от того, что клиент и сервер поддерживают, даже не заботясь о вас… это звучит интересно? Если ответ «да», следите за обновлениями для некоторых последующих сообщений …