Клиент-сервер в HL и CS
!!subpageslist!!
Newbie, newbie@nashalife.ru




" Перевод: Newbie

" Оригинал статьи

Коммуникации клиент-сервер

Клиент - программа Half-life используемая игроком для подключения к серверу. Сервер Half-Life - центральная программа, к которой могут подключаться клиенты для игры в Half-Life и его модификации, например Counter-Strike.

Клиенты не общаются друг с другом, только с сервером. Сервер следит за тем, что делаеткаждый клиент и как они влияют друг на друга и сообщает клиентам то, что им необходимознать.

Если представить картинку схематично, то мы получим что-то вроде звезды, с сервером в середине и расходящимися от него соединениями к клиентам в виде лучей.

При общении сервера с клиентом используются два основных понятия - ширина канала (bandwidth) и задержка (latency).

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

В реальности, существует лимит данных, которые можно передать между клиентом и сервером за секунду - ширина канала и время, за которое эти данные передаются - задержка.

Ограничение ширины канала происходит двумя способами.

Во-первых, на сервере выставляется настройка, ограничивающая максимальное значениеширины канала, которое сервер может использовать для общения с одним клиентом. Врезультате, даже если клиент соединяется через выделенный канал или xDSL, пропускнаяспособность которого не меньше 64 килобайт в секунду, сервер все равно будет передаватьсо скоростью не более чем 8 килобайт в секунду (стандартное значение, которое однакоможет меняться в зависимости от сервера). Это - ограничение со стороны сервера.

Это делается потому, что большое количество "скоростных" клиентов "съедят" слишкомбольшой объем трафика, за который соответственно необходимо платить. Выставление болеевысокого лимита имеет легко предсказуемые финансовые последствия.

Во-вторых, клиенты с менее скоростным соединением (56k модемы) обычно не имеютдостаточной ширины канала для достижения максимума, выставленного на сервере. В данномслучае работает ограничение со стороны клиента.

Задержка в основном зависит от типа соединения клиента (56k модем, ISDN, xDSL и т.д.).Чем больше задержка, тем больше времени требуется для передачи данных. Чем меньшезадержка, тем лучше.

Тип соединения Ширина канала Задержка
56k модем Низкая Высокая
ISDN Низкая Низкая
xDSL Высокая Низкая
Спутник Высокая Высокая

Заметьте, что задержка никак не зависит от ширины канала. Именно поэтому напримеродноканальный ISDN имеет ту же задержку, что и двухканальный ISDN, а спутниковый канал -хотя и способен передавать мегабайты в секунду - бесполезен для игр в реальном временииз-за задержки в районе 2000 миллисекунд (ms).

" Перевод: Newbie

" Оригинал статьи

Вопросы ширины канала

Основная проблема с тем, что послан может быть только конечный объем данных состоит в том, что если в какой то момент происходит столько событий, что сервер вынужден послать больше данных, чем клиент способен принять, чем-то придется пожертвовать. Что же произойдет если какие то данные - потенциально критичные данные, например выстрел игрока - просто не были посланы?

Представьте себе игрока с модемом 56k. В данном случае скорость передачи от клиента ксерверу составляет 3 килобайта в секунду, а от сервера к клиенту - 5 килобайт в секунду(большинство типов соединения имеют асинхронны, то есть в одном направлении могутпередавать быстрее чем в другом).

Для начала наш игрок ходит в пустой части карты. ничего особенного не происходит, кромесмены его позиции и клиент передает минимум данных серверу - грубо говоря 1 килобайт всекунду. Соответственно и серверу нечего сообщать клиенту, так как рядом с ним ничего непроисходит.

Теперь наш игрок сворачивает за угол и оказывается в самом центре боя. Неожиданно егоклиент должен получить множество информации - вокруг много игроков, много выстрелов,гранаты летают и т.д. Сервер начинает усиленно передавать и в какой то момент долженпослать 10 килобайт данных в секунду, но наш клиент может принять только 5. Чтопроисходит в результате? Сервер просто не может передать полные 10 килобайт и долженвыбрать, какие 5 отбросить, а какие 5 все таки послать.

Как вы можете себе представить - Это Не Есть Хорошо.

Как именно это делается относится к тому, как именно организовано общение. Честно говоря, сервер может отбросить достаточно много данных ничего в реальности, не испортив для клиента.

Игры в реальном времени протекают очень похоже на фильм - чем чаще обновляется экран,тем реалистичнее выглядит кино. В данном случае вместо кадров выступает количествообновлений информации, которую клиент имеет о происходящем вокруг.

Представьте что сервер сообщает клиенту о происходящем только раз в 5 секунд. Клиентбудет видеть, как игроки перескакивают на огромные расстояния, вообще не будет видетьгранат и вероятно будет умирать так и не увидев противника.

Теперь представим обновление раз в секунду. Улучшение будет значительным - игроки будутдвигаться почти плавно, гранаты будут видны, но прицеливание будет все равно значительнозатруднено.

Теперь вообразим обновление 25 раз в секунду. наш игрок в деле! Клиент обновляетсянастолько часто, что достигается почти полная иллюзия естественности движения.

Однако здесь то и кроется конфликт. Чем чаще сервер посылает обновления, тем большеданных в секунду необходимо передать. Если данных слишком много, если их больше чем каналклиента может выдержать, сервер начнет отбрасывать данные.

Когда это происходит, сервер просто временно уменьшает частоту обновлений. Мир со стороныигрока станет более дискретным, но останется функциональным.

Если напротив, клиент посылает слишком много данных серверу, клиент уменьшит частотусвоих обновлений.

Важно помнить, что чем больше событий происходит вокруг игрока, тем больше данныхпосылается с каждым обновлением. Поэтому 35 обновлений в секунду могут работать идеальнона пустынной карте, но начнут "лагать" в бою.

Именно здесь игрок может приложить свою руку при настройке клиента. Ширина канала -величина фиксированная, но количество обновлений полностью в руках пользователя. Этодает игроку грубый, но эффективный контроль над количеством посылаемых данных (грубыйпотом, что количество данных, посылаемых за раз не постоянно и контроля над этим упользователя нет).

Сетевая настройка в Half-life - это вопрос знания того, какова ширина канала в вашемраспоряжении и вычисления сколько обновлений вы можете выдержать без нарушений связи вразгар боя.

" Перевод: Newbie

" Оригинал статьи

Вопросы задержки

Как упомянуто ранее, задержка в соединении является одним из главных факторов, влияющихна процесс общения клиента с сервером.

Основная проблема такова: Сервер получает от всех клиентов информацию о том что ониделают. Далее сервер непрерывно обновляет состояние мира Counter-Strike на основе этойинформации и сообщает всем клиентам о текущем состоянии.

Теперь предположим что игрок нажал кнопку идти вперед. Через 250ms сервер получает этуинформацию. До этого момента этого движения не существует, потому что сервер о нем незнал.

Когда сервер узнал о движении, он обновляет позицию игрока и сообщает всем клиентам чтоигрок передвинулся.

Еще 250ms спустя все клиенты получают эту информацию и наконец-то видят изменения наэкране.

Все отлично, кроме того факта, что игрок был на этой позиции пол секунды назад! То чтокаждый игрок видит на экране - это позиция игрока примерно пол секунды назад.

Есть еще одна особенность, которую необходимо понимать. Есть разница между тем, чтоделает игрок (в данном случае 500ms назад) и тем, что знает о нем сервер (250ms назад).

Когда игрок прицеливается и стреляет значение имеет только позиция, о которой знаетсервер, а не позиция, о которой знает клиент, ведь информация об этом еще не дошла досервера.

Так что, когда игрок целится и стреляет, он целится в позицию противника, которую тотзанимал 500ms назад с точки зрения этого противника, но только 250 ms назад с точкизрения сервера.

Естественно, что если бы все было именно так, нормальное прицеливание было бы оченьзатруднено.

Решение этой проблемы достаточно просто. Сервер сохраняет историю передвижений игроковза последние полсекунды или около того. Когда информация о выстреле достигает сервера,сервер знает сколько она к нему шла (допустим 241ms для данного конкретного выстрела) итакже знает среднюю задержку цели (предположим 70ms). В результате сервер смотрит историюпозиций по сумме этих двух значений (311ms) и проверяет была ли в момент выстрела цельточно в перекрестии прицела.

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

Таким образом игроки могут прицеливаться нормально, не вычисляя позиций.

Также, это причина, по которой игроки иногда умирают уже после того, как они забежали заугол, где их вроде бы не видно. В них попали до того, как они забежали за угол, но серверпонял это несколько позднее и еще позже об этом узнал клиент убитого игрока.

Клиент может сам выбирать, желает ли он использовать историю позиций на сервере (то естьжелает ли он целиться прямо в цель или предсказывать ее позицию самостоятельно).

Делается это с помощью команды cl_lc. Установленная в 1, она приказывает клиентуиспользовать историю, при значении 0 - не использовать.

Ниже четко показана разница:

cl_lc 1 cl_lc 0

На левом видео показан клиент, использующий историю. Пистолет выстрелил когда цельпересекла прицел. Некоторое время спустя данные достигли сервера, который проверилисторию, вычислил попадание. Далее об этом от сервера узнал клиент цели и модельдернулась от попадания.

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

" Перевод: Newbie

" Оригинал статьи

Настройка сетевых переменных

Различными параметрами сетевой настройки управляют четыре команды:

cl_cmdrate - количество раз в секунду, которые клиент сообщает о своих действиях серверу. Помните, что объем данных, передаваемых за одно обновление зависит от происходящего вокруг.

cl_updaterate - количество раз в секунду, которые сервер сообщает о происходящем на карте клиенту. Точно также, чем больше событий происходит, тем больше объем данных за одно обновление.

cl_rate - устанавливает ограничение количества байт в секунду, которые клиент может послать серверу. Это значение необходимо, так как сервер не может точно вычислить возможности соединения клиента. Значение должно совпадать со скоростью исходящей передачи вашего соединения.

rate - устанавливает лимит байт в секунду, которые сервер может передать клиенту. Со стороны сервера это значение можно ограничить с помощью команды sv_maxrate.

Обновления от клиента к серверу обычно содержат очень мало данных - примерно 20 байт.

Обновления от сервера к клиенту сравнительно велики - от 30 байт на тихих участках картыдо 175 байт в бою.

Для примера, модем 56k имеет максимальную исходящую ширину канала 33.6k, и входящую - 56k. Эти значения - бит в секунду (то есть 33600 бит в секунду). Однако это - общее значение, а не количество данных, то есть часть из этого используется на собственно поддержание соединения и сигнализацию (примерно 10 процентов) и только часть может содержать реальные данные. В результате соединение на 33.6k в реальности может передавать реальные данные только со скоростью 30.2k, что составляет 3780 байт (для тех кто не знает - в одном байте - 8 бит) - и это как раз значение, которому должен равняться параметр cl_rate (подразумевается идеальное соединение - если модемная линия низкого качества, скорость соответственно падает).

Соответственно, идеально соединение на 56k дает нам 56000 бит в секунду. Уменьшаем на 10процентов и получаем 6300 байт в секунду. Это и есть нужное на значение rate.

rate равняется скорости скачивания умноженной на 0.9 и разделенной на 8

cl_rate равняется скорости закачки умноженной на 0.9 и разделенной на 8

Учитывая что клиентам особо нечего сообщать серверу, в общении клиент -> сервер оченьредко возникают проблемы даже на модемах.

Отметим, что объем служебной информации различается в зависимости от типа соединения, ноэто не имеет особого значения для скоростных соединений, т.к. клиент обычно имеет большуюширину канала, чем сервер позволит ему использовать.

Дробные значения cl_rate и rate не оказывают никакого влияния и миф о том, что они улучшаю, что либо - не более чем миф.

Как упомянуто выше, обновления от клиента к серверу обычно очень малы и находятся где то в районе 20 байт. На 56k модеме с идеальной линией доступны 3780 байт в секунду, так что cl_cmdrate может быть установлен в 189. В Half-life существует ограничение на значение cl_cmdrate равное 60.

Обновления от сервера к клиенту содержат больше данных. Большие обновления (например вовремя боя) могут достигать 175 байт. Имея 6300 байт в секунду на идеальном 56k соединениимы можем выставить cl_updaterate равным 36.

cl_updaterate равняется значению rate деленному на 175

cl_cmdrate равняется значению cl_rate деленному на 20

У игроков со скоростными соединениями значения будут отличаться. Во-первых потому, что скоростное соединение обычно дает большую полосу, чем сервер позволит использовать. Соответственно значения rate и cl_rate необходимо выставлять на максимум, чтобы использовать весь доступный канал.

Максимальное значение для rate и cl_rate равняется 20,000.

Вычисление правильных значений cl_cmdrate и cl_updaterate обычно зависит от конкретного сервера, потому что значение sv_maxrate ограничивает доступную ширину канала, и соответственно влияет на число обновлений.

Как указано выше, в Half-life существует ограничение значение cl_cmdrate и cl_updaterate равное 60, однако рекомендуемое максимальное значение - 75 (больше - не меньше, верно?), которое можно уменьшать для соответствия sv_maxrate.

Команда net_graph отображает информацию о состоянии соединения между сервером и клиентом.

Интересующее нас значение - "удушье" (choke).

Choke отображает количество обновлений, которые не удалось послать по причиненедостаточной ширины канала.

Значение Потеря (Loss) - другое, редко используемое значение, которое отражает количествообновлений, которые были посланы, но не были приняты. Если игрок испытывает значительныепотери, то проблема скорее техническая и относится к самому соединению, а значит выходитза рамки этой статьи.

Запустите net_graph и следите за значением choke. Когда эффект "удушья" возникает - немного уменьшайте значения cl_updaterate и cl_cmdrate до тех пор, пока во время боя "удушье" не прекратит возникать вообще.

Основная цель - иметь максимально возможные значения cl_updaterate и cl_cmdrate, сохраняя при этом полное отсутствие "удушья".

" Перевод: Newbie

" Оригинал статьи

Различные аспекты поведения клиента

Движок Half-life обладает еще несколькими трюками, позволяющими увеличивать ощущениереалистичного окружения без задержек.

Когда игрок стреляет, клиент сразу же запускает анимацию оружия, рассчитывает траекториюпули и отрисовывает попадание в объект (miss decal или "промах") там, куда как он думаетпопала пуля - и все это несмотря на факт, что сервер еще даже не знает о выстреле, неговоря уже о том, куда ушла пуля и попала ли она во что либо. Таким образом у игрокасоздается ощущение, что окружение реагирует на его выстрелы моментально.

После обработки траектории пули и отрисовки попадания, клиент отсылает информацию овыстреле на сервер. Однако клиент не отсылает информацию о траектории пули, только тотфакт, что игрок совершил выстрел.

В результате сервер высчитывает вторую траекторию пули, которая будет иметь уже свойслучайный разброс и соответственно "та же" пуля попадает в другое место.

Вот почему на видео, приведенном ниже, отрисовывается "промах" (следы от пуль) настеклянных панелях и только потом они разбиваются.

Client side miss decals

Важно понимать, что то, что думает сервер - куда по его мнению попала пуля - и есть то,что происходит на самом деле. Клиент же просто "обманывает" игрока, создавая ощущение,что задержка отсутствует.

Если сервер думает, что пуля поразила объект, который должен реагировать на попадание,он командует клиенту отрисовать соответствующую анимацию - разбивающееся стекло, следкрови и т.д.

Если сервер думает, что игрок промазал, он ничего не делает - "промах" уже отрисован.Все "промахи" - подделка, они рисуются не там, куда в реальности попала пуля.

Клиент никогда не отрисовывает "попадание" до тех пор, пока не получает приказа отсервера (то есть пока сервер не решит, что попадание состоялось). Представьте что было быв противном случае: игрок стреляет в край стеклянной панели. Клиент думает что игрок попали разбивает стекло. После этого клиент сообщает о выстреле серверу, а тот считает чтопуля прошла мимо.

И что теперь? Не может же клиент по волшебству заново построить стекло? Конечно нет.Идея в том, что если клиент думает, что игрок попал куда то, он не делает ничего, кромеотрисовки "промаха" если его можно отрисовать на данном объекте (на стекле напримерможно, а на заложнике нет).

Однако есть маленькое исключение. Если клиент думает, что пуля попала в игрока илизаложника, он проигрывает звук попадания. В результате иногда вы можете слышать звукпопадания, когда самого попадания не случилось.

До версии 1.1.0.6 Half-life, отрисовка "промахов" на клиенте могла намного отличаться оттого, что думает сервер, особенно с полуавтоматическими снайперскими винтовками. ПатчHalf-life 1.1.0.8 исправил эту ошибку, сделав траектории клиента и сервера болееблизкими. Ситуация улучшилась и траектории стали похожи, но они все еще отличаются.

В заключении. Учитывая что клиент не может отрисовать "промах" на игроке или заложнике,если клиент думает что пуля попала, а сервер думает что промазала, эта пуля просто"исчезнет" - ведь ни попадания, ни промаха не было отрисовано.


2003 ©  Наша-Life
http://www.nashalife.ru/subjects-page102.html