Ускорение Asio UDP получить последний пакет в буфере сокета - PullRequest
0 голосов
/ 05 мая 2010

Я уже несколько дней бездельничаю Boost Asio , но я застрял в этом странном поведении. Пожалуйста, позвольте мне объяснить.

Компьютер A отправляет непрерывные пакеты udp каждые 500 мс на компьютер B, компьютер B желает читать пакеты A со своей скоростью, но хочет только последний пакет A, очевидно, самый обновленный.

До меня дошло, что когда я делаю:

mSocket.receive_from (boost :: asio :: buffer (mBuffer), mEndPoint);

Я могу получить OLD-пакеты, которые не были обработаны (почти каждый раз).

Имеет ли это какой-то смысл? Мой друг сказал мне, что сокеты поддерживают буфер пакетов, и поэтому, если я читаю с меньшей частотой, чем отправитель, это может произойти. ¡

Итак, первый вопрос: как можно получить последний пакет и выбросить те, которые я пропустил?

Позже я попытался использовать асинхронный пример документации Boost, но обнаружил, что он не выполняет то, что я хотел.

http://www.boost.org/doc/libs/1_36_0/doc/html/boost_asio/tutorial/tutdaytime6.html

Из того, что я мог сказать, async_receive_from должен вызывать метод "handle_receive" , когда приходит пакет, и это работает для первого пакета после запуска службы " «.

Если я хочу продолжить прослушивание порта, я должен снова вызвать async_receive_from в коде дескриптора. право?

НО я обнаружил, что я запускаю бесконечный цикл, он не ждет следующего пакета, он просто вводит "handle_receive" снова и снова.

Я не делаю серверное приложение, много чего происходит (это игра), поэтому мой второй вопрос: нужно ли использовать потоки для правильного использования асинхронного метода получения, есть ли пример с темы и асинхронный получат?

Ответы [ 5 ]

2 голосов
/ 05 мая 2010

Одним из вариантов является использование того факта, что когда локальный приемный буфер для вашего сокета UDP заполняется, последующие полученные пакеты выталкивают старые из буфера. Вы можете установить размер локального приемного буфера достаточно большим для одного пакета, но не для двух. Это приведет к тому, что самый новый пакет будет доставлен всегда, что приведет к удалению предыдущего пакета. Затем, когда вы запросите пакет с помощью receive_from, вы получите самый последний (и единственный) один.

Вот API-документы для изменения размера буфера приема с помощью Boost:

http://www.boost.org/doc/libs/1_37_0/doc/html/boost_asio/reference/basic_datagram_socket/receive_buffer_size.html

Пример выглядит неверным, поскольку он показывает сокет tcp, а не сокет udp, но изменить его обратно на udp должно быть легко (очевидное изменение должно быть правильным).

1 голос
/ 05 мая 2010

с Windows (конечно, XP, Vista и 7); если вы установите нулевой размер буфера recv, вы будете получать дейтаграммы только в том случае, если у вас есть ожидание возврата, когда датаграмма поступит. Это МОЖЕТ делать то, что вы хотите, но вам придется сидеть и ждать следующего, если вы отправите свой recv сразу после прибытия последней дейтаграммы ...

Поскольку вы играете в игру, было бы намного лучше, имхо, использовать нечто, построенное на UDP, а не на самом UDP. Взгляните на ENet , который поддерживает надежные данные по UDP, а также ненадежные «последовательные» данные по UDP. С ненадежными секвенированными данными вы получите только самые последние данные. Или что-то вроде RakNet может быть полезно для вас, так как оно выполняет много игровых задач, а также включает в себя вещи, подобные последовательным данным ENet.

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

0 голосов
/ 02 сентября 2013

Я думаю, что у меня та же проблема, для решения которой я читаю bytes_available и сравниваю с шириной пакета, пока не получу последний пакет:

boost::asio::socket_base::bytes_readable command(true);
socket_server.io_control(command);
std::size_t bytes_readable = command.get();

Вот документация .

0 голосов
/ 19 мая 2011

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

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

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

Это может быть так, убедитесь, что в handle_receive вы вызываете async_receive_from, только если нет ошибки.

0 голосов
/ 19 ноября 2010

P2engine - это гибкая и эффективная платформа для упрощения разработки системы p2p. Надежный UDP, транспорт сообщений, диспетчер сообщений, быстрый и безопасный сигнал / слот ...

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