s7106500
@s7106500

Нужно ли сжимать данные при передаче клиент-сервер? Как должен работать сервер?

Пишу программу на C++ .
Данные от клиента передаются на сервер 2-3 раза в секунду. На сервере идет расчет и высылается ответ.
Передача через сокеты Win API.
Клиентов около тысячи. Сервер один.

Посчитал, что в среднем за запрос клиент шлет 1 кб данных.

Вопроса два:

1. Один кб данных в запросе это много или мало по нынешним меркам? Я могу ужимать, данные но нужно ли?...
Я могу сжать данные до 300 байт.
Или слать только измененные данные.

Вопрос 2:
Такая логика работы сервера нормальная:

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

Другой вариант: сервер в цикле собирает со всех данные, потом отдельным циклом расчитывает и в третьем цикле всем все отправляет

Как правильнее делать?
  • Вопрос задан
  • 208 просмотров
Пригласить эксперта
Ответы на вопрос 4
GavriKos
@GavriKos
1) Надо жать или нет - решать вам. Может у вас там гигабитная локалка и критичность к производительности сервера/клиента. Или наоборот - GPRS.
2) Правильно - отдельный поток на отдельный коннект со всей логикой. ИМХО.
Ответ написан
Комментировать
alexsandr0000
@alexsandr0000
Программист C#/C++/C
1. Если сервер мощный, то лучше данные сжимать, т.к. вы сэкономите на времени, которое тратится на копирование из буфера в буфер и есть большая вероятность, что все будет передано одним кадром, а не будет сегментироваться;
2. Обычно, при подключении к серверу, создается новый поток, который и работает с клиентом (обрабатывает приходящие данные и отправляет ответ). Хотя я бы посоветовал, со временем перейти на асинхронную модель, но если проект не подразумевает развития, можно не заморачиваться.
Ответ написан
Комментировать
@AlexHell
Не правильно " отдельный поток на отдельный коннект со всей логикой" , автору лучше смотреть на асинхронные сокеты, на java есть netty. Если серв голый CPP также то не подскажу, но есть также асинхронные серваки 100%.

Смысл того что я далее пишу в том чтобы
1) не пострадать от огромного числа перключений контекста ОС изза сотен или тысяч потоков
2) не плодить лишние lock в game логике

Логика работы netty как фреймвор сетевой, можно слушать событие получения данных из сокета и их сразу обрабатывать в 1 из 4 потоков, без блокировок, внешнего взаимодействия (бд и т.п блокируют и долго отрабатывают поэтому нельзя), либо ставить в очередь (lock на структуре данных, например ArrayBlockingQueue) и во внешнем worker потоке обрабатывать. Если хотите можно многопоточно обрабатывать, но чтобы был толк - лучше разделить разные worker по разным источникам (например 1 worker thread на четные GameId, 2й на нечетные, все Game имеют GameId который назначается при старте игры).

По сжатию конкретно - если есть возможность быстро сжать то сжимайте. Передавать дельту опасно из-за потери пакетов или их пере упорядочивания если UPD, на TCP же порядок пакетов гарантируется и потери пере-посылаются и сжимать еще и дельтой поэтому можно. Тут я говорю про дельту отдельно т.к. это еще "сжатие" специфичное. Но в шутерах например можно передавать полные текущие координаты - так надежней и проще. Если у вас сложней логика и много чего передается, то думать вам.
Но в любом случае потребует ресурсов CPU на серваке. Пробуйте lz4, еще что-то быстрое, конкретных алгоритмов сжатия много, а что вам подойдет и что будет быстро не знаю.

Если у вас шутер или экшен сетевой, с архитектурой может подойти:
-- клиент шлет N раз (3 раза в сек у вас, но в шутерах делают и 30 раз)
-- серв расчитывает игровые тики (столкновения, попадания, урон, движения) U раз
-- серв шлет Y раз ответы клиентам (в отдельном таске и цикле вероятно, чтобы все клиенты получали отсечку после расчета одного и того же игрового тика сервом) в шутерах делаю 30 раз в сек, может отчаться от N)

Но вообще при расчетах на серваке, на клиентах еще может пригодиться интерполяция и предсказания (экстраполяция) (т.к. в моменты пока от серва нет данных - надо чтобы чтото двигалось) или машина времени (откатывать, если предсказал неверно).
Ответ написан
Комментировать
Demanoidos
@Demanoidos
безнравственный извращенец с богатой фантазией
В вашем вопросе нет информации о том, что за расчёты вы делаете. Для отдельных пользователей или что-то глобальное, результат чего нужен всем без исключения клиентам. От этого напрямую зависит логика сервера.

Насчёт сжатия — ответ простой. Не важно, много или мало вы передаёте. Исходите из того, нужно вам экономить трафик или нет. Если будете паковать данные — потеряете в производительности. Банально посчитайте, сколько времени будет уходить на упаковку и распаковку данных и уложитесь ли вы в нужное вам время, будет ли бонусом экономия трафика, если у вас плохой коннект клиента и на сжатии вы выиграете время.

Насчёт опроса тредов — вам уже ответили. Перебирать 1000 потоков, ожидая, что там что-то есть — неправильно. Потеряете время на переключении контекста. Для сервера с таким количеством подключений нужна событийная модель.
Ответ написан
Комментировать
Ваш ответ на вопрос

Войдите, чтобы написать ответ

Похожие вопросы