LINUX.ORG.RU
ФорумTalks

Вопрос сетевым спецам. UDP vs TCP в MMORPG/MMOFPS.


0

0

Продолжение темы про 3D-мир :)

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

Нужно минимизировать время отклика, не повышая загрузку сервера.

Классическое решение, применяемое всюду - это TCP.

geek говорит о более эффективной реализации задачи через UDP.

По скорости - согласен.

Проблема в том, что в моём представлении основная часть игровых команд требует подтверждения о передаче. С TCP это гарантируется. С UDP придётся отсылать подтверждение о получении. Т.е. с одной стороны клиент (при отсутствии ошибок) быстрее получит пакет и начнёт действовать, с другой - серверу придётся помнить об этом пакете (в то время, как TCP-пакет просто тупо будет отправлен и забыт), при отсутствии подтверждения через заданное время перепосылать его или предпринимать какие-то действия и т.п.

Плюс к этому за счёт пакетов подтверждения возрастает трафик.

Ваши соображения? Кто-то на практике с этим вопросом сталкивался?

★★★★★

Просто тебе придется делать самому то, что за тебя делал бы TCP. В силу специфичности задачи, у тебя есть шанс сделать это более эффективно, чем в TCP.

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

anonymous
()

Факт в том, что в конечном итоге udp приведёт к лагам. Спору нет, он шустрее, но вот когда упираешся в решение проблемы получения\отправки подтверждения, вот тогда станет понятно, почему всё-таки повсеместно делают выбор в пользу tcp. Хотя и более-менее жизнеспособного алгоритма подтверждений я, честно говоря, не видел. Сам упирался в эту проблему. Может у вас что-то выйдет.

Anoxemian ★★★★★
()

посмотри библиотеку RakNet, ребята слабали низкоуровневый протокол с поддержкой keep-alive, такой же быстрый как UDP, но без тормозов TCP.

lester_dev ★★★★★
()

> Проблема в том, что в моём представлении основная часть игровых команд требует подтверждения о передаче. С TCP это гарантируется.

> С UDP придётся отсылать подтверждение о получении. Т.е. с одной стороны клиент (при отсутствии ошибок) быстрее получит пакет и начнёт действовать, с другой - серверу придётся помнить об этом пакете (в то время, как TCP-пакет просто тупо будет отправлен и забыт), при отсутствии подтверждения через заданное время перепосылать его или предпринимать какие-то действия и т.п.

TCP не гарантирует, что после send(2) ваша команда в целости и сохранности попадёт на сервер. она туда может вообще не попасть (упала сеть в процессе передачи). so если протоколу следующего уровня актуально подтверждение о действительном принятии команды удалённым сервером, то это всё равно придётся делать руками что для TCP что для UDP, но в случае с TCP мороки конечно меньше.

// wbr

klalafuda ★☆☆
()
Ответ на: комментарий от lester_dev

RakNet: "On a Athlon 3000, with the included loopback test, RakNet was able to sustain 25,000 messages per second between three instances of the test application on the same computer. Message overhead ranges from 1 to 4 bytes per message, depending on features used."

Не совсем понял. Они говорят, что протокол способен гонять между тремя приложениями на одной и той же машине 0.8 мбит? Или это опечатка?

Anoxemian ★★★★★
()

> UDP vs TCP

UDP wins!!!

Мспользовал UDP для опроса статистики. Подтверждение не обязательно, достаточно ввести в пакет понятие sequence и внутреннюю команду на replay_sequence и либо дорабатывать поток команд на стороне сервера (к примеру если объект проходит цепочку состояний n1-n2-n3 но присланы данные только о n1 и n3, состояние n2 вполне легко проигнорировать). В случае острой необходимости при нарушении sequence слать запрос о повторении пакета описывающего состояние n2. Усложняется серверная часть, но неплохо устраняются транспортные проблемы.

iBliss
()

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

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

Таким образом, главное — определить, какие именно задачи будет выполнять клиент, а какие — сервер. И сделать это нужно до того, как создавать протокол.

anonymfus ★★★★
()
Ответ на: комментарий от iBliss

>Подтверждение не обязательно, достаточно ввести в пакет понятие sequence и внутреннюю команду на replay_sequence

Хорошая мысль, надо обдумать.

KRoN73 ★★★★★
() автор топика
Ответ на: комментарий от anonymfus

>Таким образом, главное — определить, какие именно задачи будет выполнять клиент, а какие — сервер. И сделать это нужно до того, как создавать протокол

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

KRoN73 ★★★★★
() автор топика
Ответ на: комментарий от KRoN73

посмотри еще сорцы кутри, там есть интересный механизм client prediction (Кармак - бох!) при большом лаге

lester_dev ★★★★★
()

> Классическое решение, применяемое всюду - это TCP.

Приснилось?

Классическое решение, применяемое всюду - это UDP.

birdie ★★★★★
()
Ответ на: комментарий от birdie

>Классическое решение, применяемое всюду - это UDP.

Ну, по факту MMORPG сегодня - это TCP :) Только, вот, с подачи geek'а выяснилось, что WWII на UDP начинает переходить,

KRoN73 ★★★★★
() автор топика

Во-первых, бояться увеличения трафика не надо. ТСР делает то же самое, вообще говоря (не надо только говорить тут про окна и прочее). Поскольку задача частная, возможен и более оптимальные решения, нежели примененные в ТСР.

Но тут наступает во-вторых, проблема с файерволлами. Для ТСР она решается гораздо проще.

anonymous
()
Ответ на: комментарий от KRoN73

Делай на UDP + какой то метод проверки доставки для критически важных пакетов (т.е. можно и в скорости выиграть и доставку гарантировать важной информации). Хотя, можно наверно и чисто UDP, но через какие то промежутки времени чтоб клиент и сервер обменивались пакетами, типа да, "на связи":) Или объедени эти 2 варианта - самое оно:)

Toxa
()

oftop>Нихрена вы не сделаете. Да ещё и на питоне.

anonymous
()
Ответ на: комментарий от anonymous

В общем, я сейчас полез возиться с тестами и...

>Но тут наступает во-вторых, проблема с файерволлами.

Не это ли я получил.

В общем, делаю такой эхо-сервер:

#!/usr/bin/env python 

import socket
sock = socket.socket(socket.AF_INET,socket.SOCK_DGRAM)
sock.bind(('',7779))
# loop waiting for datagrams 
try:
  while True:
    data, address = sock.recvfrom(8192)
    print "Datagram '"+data+"' from", address
    sock.sendto(data,address)
    print "Echo"

finally:
  sock.close()

и такой клиент:

#!/usr/bin/env python 

import socket
sock = socket.socket(socket.AF_INET,socket.SOCK_DGRAM)
data = """A few lines of data 
to test the operation 
of both client and server."""
for line in data.splitlines():
  sock.sendto(line,('airbase.ru',7779))
  print "Sent:", line
  response = sock.recv(8192)
  print "Received:", response
sock.close()

К сожалению, единственная машина, кроме тестовой с прямым IP без
Питона стоит. При работе с локалхоста - всё ок.

При подсоединении из-за NAT'а до сервера пакет доходит, ответ он
отсылает ('Echo' в выводе), но клиент ответа так и не получает.

Это из-за firewall'а? Если да - то полный облом для UDP.

KRoN73 ★★★★★
() автор топика
Ответ на: комментарий от KRoN73

>При подсоединении из-за NAT'а до сервера пакет доходит, ответ он отсылает ('Echo' в выводе), но клиент ответа так и не получает.

>Это из-за firewall'а?

Ну да, порты надо пробрасывать.

anonymous
()
Ответ на: комментарий от KRoN73

>Это из-за firewall'а? Если да - то полный облом для UDP.

Конфигурацию цепочки INPUT в студию. Может быть там явно прописан запрет для UDP.

Macil ★★★★★
()
Ответ на: комментарий от anonymous

>Ну да, порты надо пробрасывать.

На домашней машине - переброшены :-/

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

Тогда вопросов, в общем, нет :-/ Остаётся только TCP.

KRoN73 ★★★★★
() автор топика
Ответ на: комментарий от Macil

>Конфигурацию цепочки INPUT в студию

NAT на железном Zyxel P-660HT EE. Порты он не различает, TCP и UDP настраиваются вместе. Выделено два отдельных диапазона, для рабочей машины и для жены (p2p и др.), всё остальное - один в один мапится на домашний серверок. С него и тестировал.

Т.е. _вообще_ UDP пашет. Та же KAD работала, пока юзал aMule.

KRoN73 ★★★★★
() автор топика
Ответ на: комментарий от KRoN73

Хотя ещё возможен вариант, когда клиент соединён с сервером в два потока и отсылает ему данные по UDP, а получает - по TCP.

Вопрос, стоит ли такая фигня такого усложнения :)

KRoN73 ★★★★★
() автор топика
Ответ на: комментарий от KRoN73

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

udp так же пролезает через NAT, как и TCP. В смысле, если правило -SNAT --to-source не выставлено только для tcp

geek ★★★
()
Ответ на: комментарий от KRoN73

>В общем, делаю такой эхо-сервер:

через NAT dlink'овского рутера проходит

$python echocli.py
Sent: A few lines of data
Received: A few lines of data
Sent: to test the operation
Received: to test the operation
Sent: of both client and server.
Received: of both client and server.

geek ★★★
()
Ответ на: комментарий от geek

Ну уж если аж до такого возраста этим занимаетесь то попробуйте состряпать это на icmp

anonymous
()
Ответ на: комментарий от geek

>udp так же пролезает через NAT, как и TCP.

Должен, но в реальной жизни тсп пролезает гораздо чаще удп.

anonymous
()
Ответ на: комментарий от anonymous

>Должен, но в реальной жизни тсп пролезает гораздо чаще удп.

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

geek ★★★
()
Ответ на: комментарий от geek

>udp так же пролезает через NAT, как и TCP

В любом случае нам это, увы, не подходит. Очень много клиентов с "серыми" IP :-/

KRoN73 ★★★★★
() автор топика
Ответ на: комментарий от KRoN73

>В любом случае нам это, увы, не подходит. Очень много клиентов с "серыми" IP :-/

блин. У меня серый IP. Я за двумя NAT щас сижу. И работает.

geek ★★★
()
Ответ на: комментарий от KRoN73

>один в один мапится на домашний серверок

А на сервере? У меня например, в CentoOS5 достаточно параноидальная конфигурация файрволла по дефолту...

Macil ★★★★★
()
Ответ на: комментарий от geek

>Блин. У меня серый IP. Я за двумя NAT щас сижу. И работает.

Проходит что, ответ по UDP?

Почему тогда у меня не проходит?

Почему народ говорит о том, что входящие UDP для этого надо заворачивать? :)

KRoN73 ★★★★★
() автор топика
Ответ на: комментарий от Macil

>А на сервере?

А на сервере:

# iptables -L
Chain INPUT (policy ACCEPT)
target     prot opt source               destination         

Chain FORWARD (policy ACCEPT)
target     prot opt source               destination         

Chain OUTPUT (policy ACCEPT)
target     prot opt source               destination 

KRoN73 ★★★★★
() автор топика
Ответ на: комментарий от KRoN73

>Проходит что, ответ по UDP?

угу

>Почему тогда у меня не проходит?

настройки рутера смотри

>Почему народ говорит о том, что входящие UDP для этого надо заворачивать? :)

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

geek ★★★
()
Ответ на: комментарий от geek

>настройки рутера смотри

От роутера _ничего_ не должно зависеть. Ибо масса клиентов заняться такой настройкой просто не сможет. Посему всё, что потребует особых телодвижений юзера - идёт в топку автоматом. Это проект не для гиков :)

>если бы у тебя _сервер_ был с серым ip, до для того чтобы достучаться до него из инета - нужно делать маппинг портов на рутере

Ты не поверишь, но вот всё остальное до моего сервера с IP 192.168.1.3 снаружи, по реальном IP роутера доступно. И веб-сервер, и ssh по TCP и KAD по UDP. Т.е. понятно, что чудес не бывает, и где-то глюк, и я, в конце концов, с ним могу разобраться, но я буду не единственый юзер предполагаемого проекта. У простых же юзеров для настройки NAT'а может либо не быть квалификации, либо вообще - возможности.

KRoN73 ★★★★★
() автор топика
Ответ на: комментарий от KRoN73

>От роутера _ничего_ не должно зависеть. Ибо масса клиентов заняться такой настройкой просто не сможет. Посему всё, что потребует особых телодвижений юзера - идёт в топку автоматом. Это проект не для гиков :)

извини, если на рутере запретить форвардинг udp и tcp - то вообще нихрена работать не будет. Давай сразу астральный канал для связи проектировать.

>Ты не поверишь, но вот всё остальное до моего сервера с IP 192.168.1.3 снаружи, по реальном IP роутера доступно. И веб-сервер, и ssh по TCP и KAD по UDP. Т.е. понятно, что чудес не бывает, и где-то глюк, и я, в конце концов, с ним могу разобраться, но я буду не единственый юзер предполагаемого проекта. У простых же юзеров для настройки NAT'а может либо не быть квалификации, либо вообще - возможности.

я много железок перепробовал. Везде по умолчанию разрешен форвардинг и tcp и udp.

geek ★★★
()

А почему нельзя сделать 2 соединение - TCP для того, что должно быть доставлено, и UDP для того, что можно и потерять? Боитесь перегрузить сервер?

> Проблема в том, что в моём представлении основная часть игровых команд требует подтверждения о передаче.

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

Иногда бывает важно последнюю команду передвижения не потерять, чтоб объект так и не остался стоять не на том месте... тут можно несколько раз еще послать после остановки +10 байт в трех UDP пакетах вроде роли не играют...

gods-little-toy ★★★
()

Раз уж тут так много постов, выскажу свое мнение. TCP и UDP примерно одинаково проходят через маршрутизаторы, хотя NAT TCP немного предпочтительнее --- у UDP нет понятия "соединия" поэтому через 5 минут простоя запись о NAT'е исчезает, но для игры это не важно, так как там все время идет трафик. Второе, некоторые, совершенно отмороженные админы домашних сетей полностью перекрывают UDP, но при этом они обычно перекрывают и много TCP портов, то есть опять никакой принципиально разницы.

Есть еще третий аргумент, но это только моя догадка, в общем несколько раз я сравнивал нагруженные Cisco в плане пропускания UDP и TCP, у меня получалось, что Cisco отдает предпочтение TCP пакету. То есть, грубо говоря, если Cisco нужно сделать drop пакета, и у нее будет выбор UDP или TCP, то она уничножит UDP пакет... Естественно, исходных кодов прошивки CISCO у меня нет, я просто генерил трафик из UDP/TCP пакетов, нагружал CISCO больше 75% и смотрел какие пакеты пропадают... Особо в детали я не вдавался, от сети для экспериментов циску не отключал. В этом выводе больше интуиции и догадок, чем фактов... Но маршрутизаторы у многих провайдеров загружены очень хорошо. В общем true решение --- создать свою реализацию tcp, чтобы пакеты выглядели как tcp, а все правила отправки подтверждений, таймауты и т.д. были свои :) Но это задача и не для Питона, и ее решение может оказаться сложнее, чем вся игра, а для Питона я советую TCP. ИМХО.

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

mky ★★★★★
()
Ответ на: комментарий от anonymfus

>..., а от сервера к клиенту уже отрендеренный видеопоток c трёхмерной картинкой. ...

Нихрена себе!
Это какой-же канальчик-то надо?

ManJak ★★★★★
()
Ответ на: комментарий от geek

>извини, если на рутере запретить форвардинг udp и tcp - то вообще нихрена работать не будет. Давай сразу астральный канал для связи проектировать.

Имеется в виду мапинг входящих соединений. Неужели так трудно сообразить?

>Везде по умолчанию разрешен форвардинг и tcp и udp.

Входящих? Ну-ну. И на какой IP? :D

Исходящий UDP у меня прекрасно доходит. Читай первый постинг. Сервер данные от клиента получает. Но не _возвращает_ ответ. Точнее - ответ уходит, но клиент его не получает.

KRoN73 ★★★★★
() автор топика
Ответ на: комментарий от gods-little-toy

>А почему нельзя сделать 2 соединение - TCP для того, что должно быть доставлено, и UDP для того, что можно и потерять? Боитесь перегрузить сервер?

Возможно, со временем так и будет. Постараемся сделать командный протокол, который можно будет расширить, если что. Но сейчас - это будут лишние сущности :)

С учётом проблем ответа на серые IP, придётся делать работу в несколько потоков в зависимости от параметров клиента.

>Команд, не требующих подтверждения, может и не много, они часто используемые - "передвинуть объект obj в координаты (x,y)" и всякие жесты

Жесты я уже упоминал (social actions). А вот MoveTo обязан быть подтверждённым. Иначе возникнет рассинхронизация координат клиента и сервера.

KRoN73 ★★★★★
() автор топика
Ответ на: комментарий от KRoN73

>Имеется в виду мапинг входящих соединений. Неужели так трудно сообразить?

я не понимаю, зачем тебе маппинг входящих. У тебя на сервере серый IP?

>Исходящий UDP у меня прекрасно доходит. Читай первый постинг. Сервер данные от клиента получает. Но не _возвращает_ ответ. Точнее - ответ уходит, но клиент его не получает.

значит, у тебя что-то его режет по дороге.

geek ★★★
()
Ответ на: комментарий от KRoN73

>А вот MoveTo обязан быть подтверждённым. Иначе возникнет рассинхронизация координат клиента и сервера.

я уже писал, что из десятка MopeTo важен только последний. Если остальные потерялись - это не проблема

geek ★★★
()
Ответ на: комментарий от geek

>я не понимаю, зачем тебе маппинг входящих. У тебя на сервере серый IP?

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

Иначе как объяснить, почему ответный пакет не доходит у меня _ни на одной_ машине (в разных подсетях и с разными админами :D ) с серым IP?

Ещё раз смотри первое сообщение топика.

KRoN73 ★★★★★
() автор топика
Ответ на: комментарий от KRoN73

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

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

Клиенту же указываешь ip маршрутизатора и всё работает.

Для tcp нужны ровно такие же телодвижения.

Для клиента секс с пробросом портов не нужен.

geek ★★★
()
Вы не можете добавлять комментарии в эту тему. Тема перемещена в архив.