#c# #flash #actionscript-3 #multiplayer
#c# #flash #actionscript-3 #Многопользовательский режим
Вопрос:
Представьте себе многопользовательскую доску, на которой несколько человек могут рисовать одновременно. Для простоты предположим, что на доске есть один объект, который может быть перемещен или удален любым пользователем. Не существует понятия объектов, принадлежащих пользователю (т. е. Важно, чтобы любому пользователю было разрешено манипулировать любым объектом… это бесплатная доска для всех)
Моя проблема заключается в следующем … если два пользователя одновременно попытаются выполнить разные действия с объектом, т. е. один удалит его, а другой переместит, что произойдет?
Прямо сейчас — просто позволяя сообщениям проходить, все выходит из-под контроля.
Одна из идей состояла в том, чтобы иметь серверный элемент управления, который определяет, кто контролирует объект, и ничего не должно происходить на стороне клиента, пока этот конфликт не будет разрешен. Разрешение конфликтов может основываться на принципе «в порядке живой очереди».
Даже при том, что это может произойти очень быстро, небольшая задержка (~ 50-300 мс) неприемлема, поскольку перемещение должно быть мгновенным на стороне клиента. Например, вместо того, чтобы манипулировать объектами, подумайте о ручке. Чтобы была задержка до тех пор, пока они уже не начнут рисовать… не очень хорошо!
Другой идеей было иметь кнопку «запросить управление», которая запрашивает у серверного расширения управление …. та же идея, что и раньше, но теперь их не расстраивает начальная задержка рисования пером. Это тоже не очень хорошо, хотя, поскольку они должны нажимать на эту кнопку, пока не смогут что-либо сделать, а эта доска действительно предназначена для детей…
Есть другие решения? 🙂
Ответ №1:
Эта интересная проблема обычно решается с помощью комбинации разрешений на стороне клиента и сервера. Если вы знакомы с WoW, особенно с первыми днями выпуска, вы наверняка помните сбой сервера, и все продолжают двигаться. Это делается клиентом, управляющим предикативными перемещениями и запрашивающим периодические обновления с сервера для значений фактического местоположения и поведения.
Аналогичная идея должна быть применима к вашей проблеме. Ваше разрешение на стороне сервера на основе f.c.f.s кажется идеальным. Проблема, как вы упомянули, заключается в задержке, снижающей удобство работы пользователя. Чтобы покончить с этим, почему бы не предоставить пользователю полный контроль на стороне клиента, а затем запросить обновление с сервера после завершения операции? Таким образом, если вы переместите круг вниз на 200 пикселей, а я изменю цвет на зеленый, мы оба сможем увидеть мгновенное поведение на стороне клиента, но когда вы отпустите круг, вы также увидите, что он становится зеленым, как указано на сервере.
Очевидная проблема возникает, когда оба пользователя изменяют одни и те же свойства объекта. На этом этапе системе f.c.f.s необходимо будет принять решение относительно того, что делать, на основе использования клиентом. Должен ли он выполнять net delta для объекта? Следует ли уведомлять пользователя о том, что другой пользователь изменил объект другим способом? Это скорее вопрос функциональности, чем технический.
Комментарии:
1. Мне нравится, как вы указали, что конфликт существует только для определенных изменений свойств! т.е. color и position не являются конфликтом, но position и position или position и delete являются…
2. Я предполагаю, что только на самом простом уровне я мог бы вести историю и «вернуться назад и запретить управление», если сервер выдает сообщение о блокировке объекта…
3. простым решением конфликта с аналогичными манипуляциями со свойствами было бы установить временную метку взаимодействия с пользователем и сохранить последнее изменение (или, если объект удален, просто сохраните его удаленным)
Ответ №2:
Действительно интересный вопрос! Состояние доски хранится на сервере (например, в базе данных). На клиенте возможны 3 действия: startEditing
, finishEditing
, delete
. Сразу после выполнения какого-либо действия вы должны отправить сообщение на сервер с описанием действия.
Если startEditing
отправлено, прежде всего, вы должны проверить, не заблокирован ли объект, который вы собираетесь редактировать. Если она разблокирована, вы должны установить блокировку (блокировка должна содержать информацию о пользователе, который установил блокировку). Затем вы должны отправить сообщение всем активным клиентам, чтобы сообщить, что этот объект не следует редактировать.
Если finishEditing
(это сообщение должно содержать информацию об изменениях в объекте) отправлено, вы должны изменить объект в базе данных, снять блокировку и отправить сообщение всем активным клиентам, сообщающим об изменениях и снятой блокировке.
Если delete
отправляется. Если объект не заблокирован клиентом, отличным от того, который отправил сообщение, вам следует удалить объект из базы данных и отправить сообщение всем активным клиентам с приказом удалить этот объект с доски
Комментарии:
1. Проблема в том, что при отправке startEditing «проверка» требует проверки на стороне сервера, что приводит к задержке
2. Если первый клиент отправляет
startEditing
одновременно со вторым, некоторые из клиентов будут первыми, кто установит блокировку, а второй увидит блокировку и ничего не сделает3. да, но опять же — проблема в том, что клиент должен немедленно получить возможность рисовать, если у него будет блокировка.
4. Другими словами…. Client1 и Client2 при каждой попытке привлечь Client1 первым попадает в блокировку и получает разрешение от сервера. Только теперь Клиент1 может фактически рисовать — поэтому существует задержка между тем, когда Клиент1 нажал мышь и получил разрешение
5. А как насчет предлагаемой отправки сообщения всем активным клиентам о том, что объект заблокирован сразу после получения сервером
startEditing
сообщения? Вы будете знать, разрешить или запретить рисование без задержки
Ответ №3:
Возможно, вы сможете сделать что-то, где вы показываете взаимодействия локальных элементов и то, что когда-либо видит кто-либо еще. В начале вы показываете что-то вроде: прозрачный объект, с которым вы взаимодействуете или с которым пишете, не является окончательным, все видят, что непрозрачные объекты / рисунки являются окончательными и что бы кто ни видел.
Когда вы обнаруживаете, что 2 пользователя одновременно перемещают элемент, на их собственном экране они оба прозрачны, в ходе некоторых многопользовательских обновлений пользователь, который, как было определено, контролирует объект, все еще перемещает объект, и вы можете показать какое-то событие (возможно, общий сбой) пользователя, который перемещал свой объект, который, как теперь было определено, не находится под их контролем.
таким образом, вы получаете немедленный отклик на рисование и время от времени немного разочаровываетесь, когда выясняется, что они не контролируют элемент.
Комментарии:
1. Если я вас правильно понимаю, это та же идея, что и то, что я сказал выше — «Я предполагаю, что это только самый простой уровень, я мог бы вести историю и «вернуться назад и запретить управление», если сервер выдает сообщение о блокировке объекта … » НО вы добавили визуальный сигнал на стороне клиента, чтобы они могли отличать объект, который действительно переместился, от возможной временной попытки перемещения … ? Это верно? Мне это нравится!