Императорская Моль 🕊
Понял, спасибо
Snusmumriken
Все сложносочинённые ключи делаются через квадратные скобки.
local mytable = {}
othertable = {
[mytable] = 1
}
local foo = mytable
othertable[foo] --> 1
othertable.foo --> nil, в данном случае foo это строка, как othertable["foo"]
То же самое со всякими числами если тебе нужны дырки, сложносоставными (или даже многострочными) ключами и так далее.
Александр
Wsevolod
Я правильно понимаю, что luasocket не умеет в unix-овские сокеты?
Wsevolod
Возьму luv тогда
Snusmumriken
Luasocket про кроссплатформу.
Snusmumriken
Для кроссплатформенной многопоточности можно дёргать lanes или другие либы дающие то же самое. Для общения между разными, не связанными друг с другом процессами можно использовать обычный luasocket, делая запросы на localhost аналогично юникс-сокетам с всего лишь чуть меньшей скоростью обмена но кроссплатформенностью. Для подсоединения к уже реализованному кем-то приложению с юникс-сокетами — в любом случае понадобятся именно они, возьми что-то ещё, как раз вроде luv.
Лично я советую использовать кроссплатформенные варианты везде где возможно, мало ли как что обернётся.
Wsevolod
Snusmumriken
Лады.
Wsevolod
А есть пример luasocket с unix?
Snusmumriken
Нет, luasocket не умеет в unix, но можно общаться между процессами по TCP, с тем же результатом в большинстве случаев но с кроссплатформой. Перечитай.
Wsevolod
Igor
Для кроссплатформенной многопоточности можно дёргать lanes или другие либы дающие то же самое. Для общения между разными, не связанными друг с другом процессами можно использовать обычный luasocket, делая запросы на localhost аналогично юникс-сокетам с всего лишь чуть меньшей скоростью обмена но кроссплатформенностью. Для подсоединения к уже реализованному кем-то приложению с юникс-сокетами — в любом случае понадобятся именно они, возьми что-то ещё, как раз вроде luv.
Лично я советую использовать кроссплатформенные варианты везде где возможно, мало ли как что обернётся.
Кстати, раз уж разговор об этом зашел. С чистыми luasocket и lua-lanes возможно сделать многопоточный хендлинг? Потому что мне приходилось свой бинарник luasocket собирать, сунув в метатаблицу функцию setfd, которой нет по дефолту. В итоге в одном потоке у меня работал accept(), как прилетал клиент - создавался новый поток и в него отправлялся client:getfd(), а уже внутри потока происходила магия по созданию dummy-юзердаты TCP сокета и присвоения ей полученного дескриптора.
Igor
Я что-то искал более удобное решение, но ничего не нашел.
Tverd
Обычно делается не так. Создаются потоки, один висит в ацепте, как получил дескриптор, отдает его в очередь и кто свободен - забирает. Ибо создание потока, если мы о system thread, довольно тяжёлая задача
Tverd
А недавно в линухи запилили фичу, что могут сами воркеры висеть в ацепте и если один схватил соединение, остальные не просыпаются. Раньше все посыпались
Tverd
Но это надо включать
Tverd
Ну а высший пилотаж создавать треды, в которых работа идёт через асинхронщину
Yuriy
А почему тогжа нельзя на С написать многопоточный listener и оркестратор? Запустить в каждом lvm и потом уже отдавать в конкретный поток в котором со старта крутится lvm?
Tverd
Snusmumriken
Конечный результат охренителен, инфа сотка.
Snusmumriken
Обычно делается не так. Создаются потоки, один висит в ацепте, как получил дескриптор, отдает его в очередь и кто свободен - забирает. Ибо создание потока, если мы о system thread, довольно тяжёлая задача
Вот ета штука кстати называется "пул потоков", типа "в мейн-треде раскидываем задачи по свободным воркерам из пула, те делают работу, возвращают результаты, дозаполняем воркеры всякой фигнёй". Без пула, оно на завале задачами может самую малость перегрузить системку, а так получается нормальная очередь с параллельным исполнением. Но вот то что большая часть тредов занимаются ожиданием ввода-вывода ломает малину, хоть и круче по возможностям очистки стеков/убийству потоков/невозможности зафакапить тред.
Dmitrii
@kraftwerk28 @Snusmumriken @smertig @moteus писал неделю назад сюда по поводу передачи коннекшена к БД из с++ в Lua. видел ваши предложения, попробовал, но в итоге оказалось, что мою задачу нужно было решать вообще иначе (использовать динамическую lsqlite3 вместо статической). Но в любом случае спасибо большое за помощь.
Snusmumriken
А в чём принципиальная разница? У тебя там были баги какие-то? В целом, статика и динамика не должны иметь принципиальной разницы.
Dmitrii
А в чём принципиальная разница? У тебя там были баги какие-то? В целом, статика и динамика не должны иметь принципиальной разницы.
Моя проблема заключалась в том, что у меня при закрытии коннекшена в Lua исчезал WAL файл базы данных SQLite. Как выяснилось, проблема была вызвана тем, что с++ использовал один инстанс sqlite3 библиотеки (версия 3.27.2, статическая), а LUA использовал другой инстанс sqlite3 библиотеки (версия 3.24.0 - из lsqlite3 версии 0.9.5, а именно lsqlite3complete, то есть статическая lsqlite3).
Решение проблемы оказалось в том, чтобы использовать динамическую версию lsqlite3, которая линкуется динамически с libsqlite3.so, а также в с++ использовать динамическую версию sqlite3. Тем самым и LUA и с++ будут использовать один и тот же инстанс sqlite3.
Dmitrii
Для меня было неочевидно, что во-первых у меня в Луа используется другая версия sqlite3 библиотеки, а во-вторых, что 2 разных инстанса библиотеки могут приводить к таким проблемам. Поэтому казалось, что решением будет общим коннекшеном пользоваться
Snusmumriken
А, ну так два инстанса. Я как раз предлагал выгружать в луа инстанс твоей плюсовой библиотеки с метатаблицей провешенных плюсовых функций, фактически забиндить плюсовую либу в луа. И использовать буквально один хендлер и для плюсов и в луа.
Dmitrii
Igor
Ну, я на сишке когда сервер писал для игры, по интернетам рылся, искал, как лучше сделать. Не придумал ничего круче, кроме как при каждом удачном accept'e создавать структуру "Client" и в неё писать дескриптор сокета, ну а после вызвать pthread_create (или CreateThread, в зависимости от системы) и в поток передавать эту структуру. А поток уже делал с ней грязные делишки, принимая инфу от сокета и записывая её в структуру.
Igor
Обычно делается не так. Создаются потоки, один висит в ацепте, как получил дескриптор, отдает его в очередь и кто свободен - забирает. Ибо создание потока, если мы о system thread, довольно тяжёлая задача
Igor
А недавно в линухи запилили фичу, что могут сами воркеры висеть в ацепте и если один схватил соединение, остальные не просыпаются. Раньше все посыпались
Igor
Но это надо включать
Igor
Ну а высший пилотаж создавать треды, в которых работа идёт через асинхронщину
Igor
В итоге все сокеты получились блокирующими и не мешают друг-другу. Пришлось ещё, правда, костыль один навертеть, если клиент в вебе запускался, то соединение шло в вебсокетах, а не на сыром TCP, сделал в начале потока цикл из 10 шагов, который recv вызывает с флагом MSG_PEEK и ждёт "GET /", если дождался - делаем хендшейк вебсокетный и запускаем цикл получения сообщений, если не было "GET /", то как обычного клиента.
Snusmumriken
Ну, я на сишке когда сервер писал для игры, по интернетам рылся, искал, как лучше сделать. Не придумал ничего круче, кроме как при каждом удачном accept'e создавать структуру "Client" и в неё писать дескриптор сокета, ну а после вызвать pthread_create (или CreateThread, в зависимости от системы) и в поток передавать эту структуру. А поток уже делал с ней грязные делишки, принимая инфу от сокета и записывая её в структуру.
Это дичайше древняя технология, создавать тред под клиента. Первая попытка сделать так, чтобы "подсоединённый клиент не блокировал других клиентов". Правда, количество тредов обычно ограничивается цифрами 100/1000, иначе слишком много ресурсов начинает тратиться на переключение тредов и процесс становится ещё медленнее чем при однопоточке.
Igor
Igor
Так что в худшем случае будет 127 клиентов
Igor
Я думал переписать на select/poll, но не придумал, как лучше всего это сделать
Igor
А вот, собственно, и сам протокол. Тут даже динамического размера данных нет, везде статика https://wiki.vg/Classic_Protocol
Igor
Строки и те фиксированные по 64 байта.
R
На какие же извраты народ идёт, лишь бы Эрланг не учить.
Tverd
Если мы говорим о игровом сервере с большим количеством клиентов, то тут уже udp стоит использовать, точнее rudp
Snusmumriken
Хых, писал rudp-протоколы, и это довольно жестяная жесть )
Как либа отлично заходит enet, благо она даже в steamworks используется (местные сетевые пакеты через стимовую апишку пересылаются enet'ом, и на нём можно накатать серверы которые будут связаны с игрулями пользующимися протоколами из стима)
Tverd
Snusmumriken
Ну у меня там технология типа:
Первый пакет с метаданными, и куском данных + фрейм из нескольких пакетов, А посылает его Б и ждёт ответочку, мол, какой последний последовательный пакет принят, начинает пересылать дальше фреймом из нескольких пакетов начиная с последнего последовательно принятого. Короткие пакеты отсылаются одним сообщением, что плюс.
R
Tverd
Igor
А вот enet - классная штука, да. Очень удобный.
Snusmumriken
Tverd
Tverd
Во всяком случае читал о таких приколах
Leon174
Опять бекендеры набежали. А прикидывались приличными людьми, мол, луа любим.
Igor
Tverd
Snusmumriken
50к игровых клиентов?)))
Без проблем. Уменьшаешь трафик, заставляешь эти 50к клиентов посылать минимальные сообщения, объединяешь отдельные короткие сообщения в один 1кб-пакет. Для типовой игры нужно очень мало трафика.
Snusmumriken
Особенно если у тебя нет локаций где больше сотни клиентов, и каждому надо переслать данные о каждом (решается игровыми слоями).
Tverd
Тут вопросы, что раньше забьется, клиентский канал или серверный.
Snusmumriken
Карочи, 50к коннектов решаются:
1. Кластером серверов
2. Балансировкой
3. Слоями, на которые распределяются клиенты (инстансы)
И это совсем не проблема TCP или UDP, если грамотно написать с учётом игровой специфики — всё будет ок.
Tverd
Небольшая история, сервер линейки легко держал больше 5к, но когда шла осада, много людей было в одном месте и сеть у клиентов была забита, хотя сервер на 20%
Snusmumriken
Вот если ты сделаешь одну игровую комнату на все 50к клиентов — с этим не справится ни один суперкомпьютер, тупо потому что всем клиентам надо отсылать данные о каждом. Там объём трафика растёт по экспоненте в зависимости от количества игроков в одном месте.
Igor
Ну есть куда расти )
Было бы, если бы игра развивалась дальше. В 11-12 году эту версию сделали архивной сами разработчики, а те, кто не пожелал от неё отказываться, написали свой порт клиента на Си, ну и сервер на шарпе, оригинальный протокол никак не трогали. Разве что расширение для него написали. У хендшейк пакета есть зарезервированный байт, который оригинальным клиентом никак не юзается, а клиент, который поддерживает расширение протокола устанавливает его а 0x42. В общем там костыль на костыле и костылём погоняет.
Tverd
Snusmumriken
Небольшая история, сервер линейки легко держал больше 5к, но когда шла осада, много людей было в одном месте и сеть у клиентов была забита, хотя сервер на 20%
Вот в этом случае, кстати, можно смело врубать сглаживание и обновлять клиентов по частям: за четверть секунды один клиент получил данные о половине игроков, за другую четверть — о другой половине. Да, появляется некоторый лаг, но на него насрать, если хорошо сглажено. И так можно растягивать в зависимости от количества. Чем больше народа тем больше лаг, но компенсация это пофиксит. Эвристика показывает что хорошо сглаженный лаг до секунды — норм.
Igor
Ну так же было с линейкой и ВОВом )
Многие игры от этого пострадали, к сожалению. Не знаю, почему почти всегда погромисты-игроки не решаются улучшить производительность сетевого протокола, например и оставляют тот ***дец, что оставили за собой разработчики сто лет назад.
Tverd
Tverd
Snusmumriken
Ну вариант, да. Но обычно на архитектуру игрового сервера все забивают))) Ну либо я чего-то не понимаю и для fps сервера 64 человека это максимум без лагов
У FPS, в отличии от какой-нибудь РПГ, есть несколько неприятных особенностей:
1. Все действия крайне быстры и не откатываемы (у рпг можно вернуть задетого или как бы убитого на клиенте персонажа, если сервер понял что последние действия были нелегитимными из-за лагокомпенсации, а у FPS — нет);
2. Из-за особенностей быстрого перемещения и видимости, нельзя сглаживать слишком сильно, например игрок шёл к краю укрытия, а другой клиент одного из игроков на другом конце карты досглаживался что идущий к краю таки вылез из укрытия, чего на самом деле не произошло, но он уже знает что там будет челик.
Igor
У FPS, в отличии от какой-нибудь РПГ, есть несколько неприятных особенностей:
1. Все действия крайне быстры и не откатываемы (у рпг можно вернуть задетого или как бы убитого на клиенте персонажа, если сервер понял что последние действия были нелегитимными из-за лагокомпенсации, а у FPS — нет);
2. Из-за особенностей быстрого перемещения и видимости, нельзя сглаживать слишком сильно, например игрок шёл к краю укрытия, а другой клиент одного из игроков на другом конце карты досглаживался что идущий к краю таки вылез из укрытия, чего на самом деле не произошло, но он уже знает что там будет челик.
Досглаживался, интересное определение, надо запомнить😂
Snusmumriken
Ну и FPS тупо пересылают гораздо больше трафика.
Tverd
У FPS, в отличии от какой-нибудь РПГ, есть несколько неприятных особенностей:
1. Все действия крайне быстры и не откатываемы (у рпг можно вернуть задетого или как бы убитого на клиенте персонажа, если сервер понял что последние действия были нелегитимными из-за лагокомпенсации, а у FPS — нет);
2. Из-за особенностей быстрого перемещения и видимости, нельзя сглаживать слишком сильно, например игрок шёл к краю укрытия, а другой клиент одного из игроков на другом конце карты досглаживался что идущий к краю таки вылез из укрытия, чего на самом деле не произошло, но он уже знает что там будет челик.
Тут ещё влияет пинг сильно, сервер надо поближе к народу ставить
Snusmumriken
У РПГ оно не настолько важно, особенно если куча вещей требуют времени каста, это автоматом растягивает трафик и ограничивает количество действий в секунду. Алсо в этом помогает ГКД.