Примечание.
Для доступа к этой странице требуется авторизация. Вы можете попробовать войти или изменить каталоги.
Для доступа к этой странице требуется авторизация. Вы можете попробовать изменить каталоги.
Предупреждение
Эта документация не подходит для последней версии SignalR. Взгляните на ASP.NET Core SignalR.
В этом руководстве показано, как создать веб-приложение, использующее ASP.NET SignalR для обеспечения функций обмена сообщениями с высокой частотой. Высокочастотное обмен сообщениями в этом случае означает, что обновления отправляются с фиксированной скоростью; в случае этого приложения до 10 сообщений в секунду.
Приложение, которое вы создадите в этом руководстве, отображает фигуру, которую пользователи могут перетаскивать. Затем позиция фигуры во всех других подключенных браузерах будет обновлена, чтобы она соответствовала положению перетаскиваемой фигуры с помощью периодических обновлений.
Основные понятия, представленные в этом руководстве, содержат приложения в играх в режиме реального времени и других приложений моделирования.
Комментарии к руководству приветствуются. Если у вас есть вопросы, которые не связаны напрямую с руководством, их можно опубликовать на форуме ASP.NET SignalR или StackOverflow.com.
Обзор
В этом руководстве показано, как создать приложение, которое предоставляет общий доступ к состоянию объекта с другими браузерами в режиме реального времени. Приложение, которое мы создадим, называется MoveShape. Страница MoveShape отобразит элемент HTML Div, который пользователь может перетаскивать; Когда пользователь перетаскивает Div, его новое положение будет отправлено на сервер, который затем сообщит всем другим подключенным клиентам, чтобы обновить положение фигуры для сопоставления.
Приложение, созданное в этом руководстве, основано на демонстрации Дэмиана Эдвардса. Видео, содержащее эту демонстрацию, можно увидеть здесь.
В учебном пособии сначала будет показано, как отправлять сообщения SignalR из каждого события, которое срабатывает при перетаскивании фигуры. Затем каждый подключенный клиент обновляет положение локальной версии фигуры при каждом получении сообщения.
Хотя приложение будет работать с помощью этого метода, это не рекомендуемая программная модель, так как не было бы верхнего предела количества отправляемых сообщений, что может привести к перегрузке клиентов и сервера сообщениями и снижению производительности. Отображаемая анимация на клиенте также будет прерывистой, так как фигура будет мгновенно перемещаться каждым из методов, а не плавно перемещаться в каждое новое местоположение. В последующих разделах руководства показано, как создать функцию таймера, которая ограничивает максимальную скорость отправки сообщений клиентом или сервером и как плавно перемещать фигуру между расположениями. Последнюю версию приложения, созданного в этом руководстве, можно скачать из коллекции кода.
В этом руководстве содержатся следующие разделы:
- Prerequisites
- Создание проекта
- Добавьте пакеты NuGet ASP.NET SignalR и JQuery.UI
- Создание базового приложения
- Добавьте цикл клиента
- Добавьте цикл сервера
- Добавление плавной анимации на клиенте
- Дальнейшие действия
Необходимые условия
Для работы с этим руководством требуется Visual Studio 2012 или Visual Studio 2010. Если используется Visual Studio 2010, проект будет использовать .NET Framework 4, а не .NET Framework 4.5.
Если вы используете Visual Studio 2012, рекомендуется установить обновление ASP.NET и web Tools 2012.2. Это обновление содержит новые функции, такие как улучшения публикации, новые функциональные возможности и новые шаблоны.
Если у вас есть Visual Studio 2010, убедитесь, что NuGet установлен.
Создание проекта
В этом разделе мы создадим проект в Visual Studio.
В меню "Файл" выберите пункт "Создать проект".
В диалоговом окне "Новый проект" разверните C# в разделе "Шаблоны " и выберите веб-сайт.
Выберите шаблон пустого веб-приложения ASP.NET , назовите проект MoveShapeDemo и нажмите кнопку "ОК".
Добавление пакетов NuGet SignalR и JQuery.UI
Вы можете добавить функции SignalR в проект, установив пакет NuGet. В этом руководстве также будет использоваться пакет JQuery.UI для перетаскивания фигуры и анимации.
Щелкните "Сервис" | Диспетчер пакетов NuGet | Консоль диспетчера пакетов.
Введите следующую команду в диспетчере пакетов.
Install-Package Microsoft.AspNet.SignalR -Version 1.1.3Пакет SignalR устанавливает ряд других пакетов NuGet в качестве зависимостей. После завершения установки у вас будут все компоненты сервера и клиента, необходимые для использования SignalR в приложении ASP.NET.
Введите следующую команду в консоль диспетчера пакетов, чтобы установить пакеты JQuery и JQuery.UI.
Install-Package jQuery.ui.combined
Создание базового приложения
В этом разделе мы создадим браузерное приложение, которое отправляет расположение фигуры на сервер во время каждого события перемещения мыши. Затем сервер передает эти сведения всем другим подключенным клиентам по мере получения. Мы развернем это приложение в последующих разделах.
В обозревателе решений щелкните проект правой кнопкой мыши и выберите "Добавить", "Класс...". Назовите класс MoveShapeHub и нажмите кнопку "Добавить".
Замените код в новом классе MoveShapeHub следующим кодом.
using System; using System.Collections.Generic; using System.Linq; using Microsoft.AspNet.SignalR; using Microsoft.AspNet.SignalR.Hubs; using Newtonsoft.Json; namespace MoveShapeDemo { public class MoveShapeHub : Hub { public void UpdateModel(ShapeModel clientModel) { clientModel.LastUpdatedBy = Context.ConnectionId; // Update the shape model within our broadcaster Clients.AllExcept(clientModel.LastUpdatedBy).updateShape(clientModel); } } public class ShapeModel { // We declare Left and Top as lowercase with // JsonProperty to sync the client and server models [JsonProperty("left")] public double Left { get; set; } [JsonProperty("top")] public double Top { get; set; } // We don't want the client to get the "LastUpdatedBy" property [JsonIgnore] public string LastUpdatedBy { get; set; } } }Приведенный
MoveShapeHubвыше класс представляет собой реализацию концентратора SignalR. Как и в руководстве 'Начало работы с SignalR', хаб имеет метод, который клиенты будут вызывать напрямую. В этом случае клиент отправит объект, содержащий новые координаты X и Y фигуры на сервер, который затем передается всем другим подключенным клиентам. SignalR автоматически сериализует этот объект с помощью JSON.Объект, который будет отправлен клиенту (
ShapeModel) содержит элементы для хранения позиции фигуры. Версия объекта на сервере также содержит элемент для отслеживания, чьи данные клиента хранятся, чтобы данные не отправлялись обратно тому же клиенту. Этот член использует атрибутJsonIgnore, чтобы предотвратить его сериализацию и отправку клиенту.Затем мы настроим концентратор при запуске приложения. В обозревателе решений щелкните проект правой кнопкой мыши и нажмите кнопку "Добавить |" Глобальный класс приложений. Примите имя Global по умолчанию и нажмите ОК.
Добавьте следующую
usingинструкцию после предоставленных инструкций using в классе Global.asax.cs.using System.Web.Routing;Добавьте следующую строку кода в
Application_Startметод Глобального класса, чтобы зарегистрировать маршрут по умолчанию для SignalR.RouteTable.Routes.MapHubs();Файл global.asax должен выглядеть следующим образом:
using System; using System.Collections.Generic; using System.Linq; using System.Web; using System.Web.Security; using System.Web.SessionState; using System.Web.Routing; namespace MoveShapeDemo { public class Global : System.Web.HttpApplication { protected void Application_Start(object sender, EventArgs e) { RouteTable.Routes.MapHubs(); } } }Затем мы добавим клиента. В обозревателе решений щелкните проект правой кнопкой мыши и нажмите кнопку "Добавить |" Новый элемент. В диалоговом окне "Добавление нового элемента" выберите html-страницу. Присвойте странице соответствующее имя (например ,Default.html) и нажмите кнопку "Добавить".
В обозревателе решений щелкните правой кнопкой мыши только что созданную страницу и нажмите кнопку "Задать как начальную страницу".
Замените код по умолчанию на HTML-странице следующим фрагментом кода.
Замечание
Убедитесь, что приведенные ниже ссылки на скрипт соответствуют пакетам, добавленным в проект в папке "Скрипты". В Visual Studio 2010 версия JQuery и SignalR, добавленная в проект, может не совпадать с номерами версий ниже.
<!DOCTYPE html> <html> <head> <title>SignalR MoveShape Demo</title> <style> #shape { width: 100px; height: 100px; background-color: #FF0000; } </style> </head> <body> <script src="Scripts/jquery-1.6.4.js"></script> <script src="Scripts/jquery-ui-1.10.2.js"></script> <script src="Scripts/jquery.signalR-1.0.1.js"></script> <script src="/signalr/hubs"></script> <script> $(function () { var moveShapeHub = $.connection.moveShapeHub, $shape = $("#shape"), shapeModel = { left: 0, top: 0 }; moveShapeHub.client.updateShape = function (model) { shapeModel = model; $shape.css({ left: model.left, top: model.top }); }; $.connection.hub.start().done(function () { $shape.draggable({ drag: function () { shapeModel = $shape.offset(); moveShapeHub.server.updateModel(shapeModel); } }); }); }); </script> <div id="shape" /> </body> </html>Приведенный выше код HTML и JavaScript создает красную фигуру с именем Shape, позволяет выполнять перетаскивание фигуры с помощью библиотеки jQuery и использует событие фигуры
dragдля отправки позиции фигуры на сервер.Запустите приложение, нажав клавишу F5. Скопируйте URL-адрес страницы и вставьте его во второе окно браузера. Перетащите фигуру в одном из окон браузера; Фигура в другом окне браузера должна перемещаться.
Добавьте цикл клиента
Так как отправка расположения фигуры на каждом событии перемещения мыши создаст ненужный объем сетевого трафика, сообщения от клиента необходимо ограничивать. Мы будем использовать функцию Javascript setInterval для настройки цикла, который отправляет новые сведения о положении на сервер с фиксированной скоростью. Этот цикл является очень базовым представлением "игрового цикла", многократно называемой функцией, которая управляет всеми функциями игры или другого моделирования.
Обновите клиентский код на HTML-странице, чтобы он соответствовал следующему фрагменту кода.
<!DOCTYPE html> <html> <head> <title>SignalR MoveShape Demo</title> <style> #shape { width: 100px; height: 100px; background-color: #FF0000; } </style> </head> <body> <script src="Scripts/jquery-1.6.4.js"></script> <script src="Scripts/jquery-ui-1.10.2.js"></script> <script src="Scripts/jquery.signalR-1.0.1.js"></script> <script src="/signalr/hubs"></script> <script> $(function () { var moveShapeHub = $.connection.moveShapeHub, $shape = $("#shape"), // Send a maximum of 10 messages per second // (mouse movements trigger a lot of messages) messageFrequency = 10, // Determine how often to send messages in // time to abide by the messageFrequency updateRate = 1000 / messageFrequency, shapeModel = { left: 0, top: 0 }, moved = false; moveShapeHub.client.updateShape = function (model) { shapeModel = model; $shape.css({ left: model.left, top: model.top }); }; $.connection.hub.start().done(function () { $shape.draggable({ drag: function () { shapeModel = $shape.offset(); moved = true; } }); // Start the client side server update interval setInterval(updateServerModel, updateRate); }); function updateServerModel() { // Only update server if we have a new movement if (moved) { moveShapeHub.server.updateModel(shapeModel); moved = false; } } }); </script> <div id="shape" /> </body> </html>Приведенное выше обновление добавляет
updateServerModelфункцию, которая вызывается на фиксированной частоте. Эта функция отправляет данные позиции на сервер всякий раз, когдаmovedфлаг указывает на наличие новых данных позиции для отправки.Запустите приложение, нажав клавишу F5. Скопируйте URL-адрес страницы и вставьте его во второе окно браузера. Перетащите фигуру в одном из окон браузера; Фигура в другом окне браузера должна перемещаться. Так как количество сообщений, отправляемых на сервер, будет регулироваться, анимация будет отображаться не так гладко, как в предыдущем разделе.
Добавьте цикл сервера
В текущем приложении сообщения, отправляемые с сервера клиенту, выходят так часто, как они получены. Это представляет аналогичную проблему, как это наблюдалось на клиенте; сообщения могут отправляться чаще, чем они необходимы, и подключение может стать перегруженным в результате. В этом разделе описывается, как обновить сервер для реализации таймера, который регулирует частоту исходящих сообщений.
Замените содержимое
MoveShapeHub.csследующим фрагментом кода.using System; using System.Collections.Generic; using System.Linq; using System.Web; using System.Threading; using Microsoft.AspNet.SignalR; using Newtonsoft.Json; namespace MoveShapeDemo { public class Broadcaster { private readonly static Lazy<Broadcaster> _instance = new Lazy<Broadcaster>(() => new Broadcaster()); // We're going to broadcast to all clients a maximum of 25 times per second private readonly TimeSpan BroadcastInterval = TimeSpan.FromMilliseconds(40); private readonly IHubContext _hubContext; private Timer _broadcastLoop; private ShapeModel _model; private bool _modelUpdated; public Broadcaster() { // Save our hub context so we can easily use it // to send to its connected clients _hubContext = GlobalHost.ConnectionManager.GetHubContext<MoveShapeHub>(); _model = new ShapeModel(); _modelUpdated = false; // Start the broadcast loop _broadcastLoop = new Timer( BroadcastShape, null, BroadcastInterval, BroadcastInterval); } public void BroadcastShape(object state) { // No need to send anything if our model hasn't changed if (_modelUpdated) { // This is how we can access the Clients property // in a static hub method or outside of the hub entirely _hubContext.Clients.AllExcept(_model.LastUpdatedBy).updateShape(_model); _modelUpdated = false; } } public void UpdateShape(ShapeModel clientModel) { _model = clientModel; _modelUpdated = true; } public static Broadcaster Instance { get { return _instance.Value; } } } public class MoveShapeHub : Hub { // Is set via the constructor on each creation private Broadcaster _broadcaster; public MoveShapeHub() : this(Broadcaster.Instance) { } public MoveShapeHub(Broadcaster broadcaster) { _broadcaster = broadcaster; } public void UpdateModel(ShapeModel clientModel) { clientModel.LastUpdatedBy = Context.ConnectionId; // Update the shape model within our broadcaster _broadcaster.UpdateShape(clientModel); } } public class ShapeModel { // We declare Left and Top as lowercase with // JsonProperty to sync the client and server models [JsonProperty("left")] public double Left { get; set; } [JsonProperty("top")] public double Top { get; set; } // We don't want the client to get the "LastUpdatedBy" property [JsonIgnore] public string LastUpdatedBy { get; set; } } }Приведенный выше код расширяет клиент, чтобы добавить
Broadcasterкласс, который регулирует исходящие сообщения с помощьюTimerкласса из платформы .NET.Так как сам концентратор является транзиторным (он создается каждый раз, когда это необходимо),
Broadcasterбудет создан как одиночный экземпляр. Отложенная инициализация (представленная в .NET 4) используется для отсрочки его создания до тех пор, пока это не потребуется, обеспечивая полное создание первого экземпляра хаба до запуска таймера.Затем вызов функции клиента
UpdateShapeперемещается из метода концентратораUpdateModel, так что он больше не вызывается немедленно при получении входящих сообщений. Вместо этого сообщения клиентам будут отправляться с частотой 25 вызовов в секунду, управляемых_broadcastLoopтаймером изBroadcasterкласса.Наконец, вместо того чтобы вызывать метод клиента напрямую из концентратора, класс
Broadcasterдолжен получить ссылку на текущий работающий концентратор (_hubContext) с помощьюGlobalHost.Запустите приложение, нажав клавишу F5. Скопируйте URL-адрес страницы и вставьте его во второе окно браузера. Перетащите фигуру в одном из окон браузера; Фигура в другом окне браузера должна перемещаться. В браузере не будет видимой разницы из предыдущего раздела, но количество сообщений, отправляемых клиенту, будет регулироваться.
Добавление плавной анимации на клиенте
Приложение почти полностью завершено, но мы могли бы сделать еще одно улучшение в движении фигуры на стороне клиента, когда она перемещается в ответ на сообщения сервера. Вместо того чтобы задать положение фигуры в новом расположении, заданном сервером, мы будем использовать функцию библиотеки animate пользовательского интерфейса JQuery для плавного перемещения фигуры между текущей и новой позицией.
Обновите метод клиента
updateShape, чтобы стать таким, как показан в выделенном коде ниже.<!DOCTYPE html> <html> <head> <title>SignalR MoveShape Demo</title> <style> #shape { width: 100px; height: 100px; background-color: #FF0000; } </style> </head> <body> <script src="Scripts/jquery-1.6.4.js"></script> <script src="Scripts/jquery-ui-1.10.2.js"></script> <script src="Scripts/jquery.signalR-1.0.1.js"></script> <script src="/signalr/hubs"></script> <script> $(function () { var moveShapeHub = $.connection.moveShapeHub, $shape = $("#shape"), // Send a maximum of 10 messages per second // (mouse movements trigger a lot of messages) messageFrequency = 10, // Determine how often to send messages in // time to abide by the messageFrequency updateRate = 1000 / messageFrequency, shapeModel = { left: 0, top: 0 }, moved = false; moveShapeHub.client.updateShape = function (model) { shapeModel = model; // Gradually move the shape towards the new location (interpolate) // The updateRate is used as the duration because by the time // we get to the next location we want to be at the "last" location // We also clear the animation queue so that we start a new // animation and don't lag behind. $shape.animate(shapeModel, { duration: updateRate, queue: false }); }; $.connection.hub.start().done(function () { $shape.draggable({ drag: function () { shapeModel = $shape.offset(); moved = true; } }); // Start the client side server update interval setInterval(updateServerModel, updateRate); }); function updateServerModel() { // Only update server if we have a new movement if (moved) { moveShapeHub.server.updateModel(shapeModel); moved = false; } } }); </script> <div id="shape" /> </body> </html>Приведенный выше код перемещает фигуру из старого расположения в новое, заданное сервером в течение интервала анимации (в данном случае 100 миллисекундах). Любая предыдущая анимация, выполняемая на фигуре, очищается до запуска новой анимации.
Запустите приложение, нажав клавишу F5. Скопируйте URL-адрес страницы и вставьте его во второе окно браузера. Перетащите фигуру в одном из окон браузера; Фигура в другом окне браузера должна перемещаться. Перемещение фигуры в другом окне должно отображаться менее дерганым, так как его перемещение интерполируется с течением времени, а не устанавливается один раз для каждого входящего сообщения.
Дальнейшие шаги
В этом руководстве вы узнали, как программировать приложение SignalR, которое отправляет сообщения высокой частоты между клиентами и серверами. Эта парадигма коммуникации полезна для разработки онлайн-игр и других имитаций, таких как игра ShootR, созданная с помощью SignalR.
Полное приложение, созданное в этом руководстве, можно скачать из коллекции кода.
Дополнительные сведения о концепциях разработки SignalR см. на следующих сайтах для исходного кода и ресурсов SignalR: