Неблокуючий UDP або окремий потік для прийому?


10

Я створюю багатокористувацьку гру (для 64 гравців). Я вже вирішив мати окремий потік для мережевого циклу, але мені було цікаво, чи було б краще створити додатковий потік для прийому UDP або встановити приймальний сокет на незаблокування (без зайвої нитки).

Або краще використовувати інший метод, як Асинхронні сокети? Кращі методи завжди вітаються!

Відповіді:


6

Гаразд, по-перше, якщо у вас щось є, і це працює, зазвичай корисно залишити це так. Чому виправляти те, що не порушено?

Але якщо у вас виникають проблеми, і ви хотіли б переписати свій мережевий код, я думаю, у вас є чотири основні варіанти:

  1. Багатопотоковий код блокування (що ви зараз робите)
  2. Неблокуючі розетки з тривожним сповіщенням
  3. Розблокування розеток із повідомленням про готовність змінити
  4. Асинхронні розетки

Написавши безліч мультиплеера (від однорангових до масово багатокористувацьких) клієнтів і серверів, мені подобається вважати, що варіант 2 призводить до найменшої складності, з досить хорошою продуктивністю, як для серверної, так і для клієнтської частини гри. Як близький другий, я б пішов з варіантом 4, але для цього зазвичай потрібно переосмислити всю вашу програму, і я в основному вважаю це корисним для серверів, а не для клієнтів.

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

Але перш за все це більшість реалізацій сокетів (і більшість реалізацій вводу-виводу в цьому випадку) не блокують на найнижчому рівні. Операції з блокування просто надаються для спрощення розробки тривіальних програм. Коли сокет блокується, ЦП у цьому потоці повністю не працює, тож навіщо будувати неблокуючу абстракцію над блокуючою абстракцією над уже неблокуючим завданням?

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

Перше, що ви хочете зробити, це встановити розетку на незаблокування. Ви робите це з fcntl().

Після цього, перш ніж робити send(), recv(), sendto(), recvfrom(), accept()( connect()трохи відрізняється) або інші виклики , які можуть блокувати потік, ви телефонуєте select()на сокеті. select()повідомляє про те, чи може бути проведена наступна операція читання або запису на розетці без її блокування. Якщо це так, ви можете сміливо робити потрібну вам операцію, і сокет не блокується.

Включити це в гру досить просто. Якщо у вас вже є цикл гри, наприклад, такий:

while game_is_running do
    poll_input()
    update_world()
    do_sounds()
    draw_world()
end

ви можете змінити його так, щоб виглядати так:

while game_is_running do
    poll_input()
    read_network()
    update_world()
    do_sounds()
    write_network()
    draw_world()
end

де

function read_network()
    while select(socket, READ) do
        game.net_input.enqueue(recv(socket))
    end
end

і

function write_network()
    while not game.net_output.empty and select(socket, WRITE) do
        send(socket, game.net_output.dequeue())
    end
end

Щодо ресурсів, то, на мою думку, всі повинні мати свої книжкові полиці, навіть якщо це єдина у них книга - це " Мережеве програмування Unix, том 1. " покійного Річарда Стівенса. Не має значення, чи займаєтесь ви Windows чи іншою ОС або програмуванням мовних розеток. Не думайте, що ви розумієте розетки, поки не прочитаєте цю книгу.

Інший ресурс, на якому можна знайти загальний огляд доступних рішень з точки зору програмування декількох сокетів (в основному стосується серверного програмування), - це ця сторінка .


Я тільки запустив свій ігровий движок, тому переписування - це не проблема. Ця відповідь була дуже корисною і дякую за книжкову рекомендацію. Ви також знаєте книгу, яка більш конкретна щодо мереж в іграх?
Янік Ланге

3
@YannickLange: Ні, але я б не рекомендував шукати спеціальні для ігор книги, оскільки мережа в значній мірі є жанрово-агностичною, а також жодна інша книга не відповідає рівню книги Стівенса. Кудо для використання UDP, хоча використання протоколу, орієнтованого на повідомлення, є хорошою ідеєю при написанні програм, орієнтованих на повідомлення (як і більшість ігор). Багато людей прагнуть закінчити написання абстракції повідомлень над TCP, що саме по собі є абстракцією, орієнтованою на потоки, побудованою над протоколом, орієнтованим на повідомлення (IP).
Піжама Panda

-1

Ви не написали, якою мовою програмування користуєтесь, але більшість мов забезпечують хороші асинхронні рамки сокетів, які часто використовують функції базової операційної системи.

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

Тому я б рекомендував вам використовувати асинхронні розетки.


4
навіщо йому потрібна нитка для кожної розетки? Особливо з асинхронними розетками? Багато важких серверів використовують модель "пулового потоку" для обробки даних сокетів, де кожен потік обслуговує N клієнтів, і вони породжуються або вбиваються в міру необхідності. Подумайте лише, що ця відповідь потребує покращення: D
Грімшо

@Grimshaw Я думаю, ти неправильно зрозумів мою відповідь. Я думаю, я зараз уточнив, що для використання блокуючих розеток потрібна буде багатопотокова модель.
Філіпп

@Philipp Я не сказав, якою мовою програмування користуюсь, тому що, я вважав, що це не дуже відповідає питанню (я, до речі, використовую c ++). Дякую за рекомендацію використовувати асинхронний сокет. Чи знаєте ви рекомендовану книгу / веб-сторінку для вивчення цих типів методів у грі (двигунах)?
Янік Ланге

@Grimshaw: А як кожен Nклієнт працює з потоком ? Якщо ви блокуєте і хочете переконатися, що кожен сокет обробляє свої дані незалежно від стану решти сокетів, у вас повинен бути один потік на сокет. Це, або не використовуйте блокуючі розетки.
Піжама Panda

Мій коментар був до першої версії вашої відповіді, тим часом ви редагували та виправляли її, забудьте, що я сказав: D
Грімшо
Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.