Как реализовать протокол, который повторно отправляет сообщения, используя BOOST ASIO

Я реализую протокол с BOOST ASIO, который повторно отправляет ответ, если он не был признан.

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

Вопрос в том, если deadline_timer истекает первым, как мне закрыть async_read_some() и попробовать прочитать новое сообщение?

Или есть лучший способ реализовать протокол, который повторно отправляет сообщения?

Если соединение tcp перестает работать, вам, вероятно, нужно закрыть сокет, который прервет read_some

Alan Birtles 10.12.2020 09:48
Стоит ли изучать PHP в 2023-2024 годах?
Стоит ли изучать PHP в 2023-2024 годах?
Привет всем, сегодня я хочу высказать свои соображения по поводу вопроса, который я уже много раз получал в своем сообществе: "Стоит ли изучать PHP в...
Поведение ключевого слова "this" в стрелочной функции в сравнении с нормальной функцией
Поведение ключевого слова "this" в стрелочной функции в сравнении с нормальной функцией
В JavaScript одним из самых запутанных понятий является поведение ключевого слова "this" в стрелочной и обычной функциях.
Приемы CSS-макетирования - floats и Flexbox
Приемы CSS-макетирования - floats и Flexbox
Здравствуйте, друзья-студенты! Готовы совершенствовать свои навыки веб-дизайна? Сегодня в нашем путешествии мы рассмотрим приемы CSS-верстки - в...
Тестирование функциональных ngrx-эффектов в Angular 16 с помощью Jest
В системе управления состояниями ngrx, совместимой с Angular 16, появились функциональные эффекты. Это здорово и делает код определенно легче для...
Концепция локализации и ее применение в приложениях React ⚡️
Концепция локализации и ее применение в приложениях React ⚡️
Локализация - это процесс адаптации приложения к различным языкам и культурным требованиям. Это позволяет пользователям получить опыт, соответствующий...
Пользовательский скаляр GraphQL
Пользовательский скаляр GraphQL
Листовые узлы системы типов GraphQL называются скалярами. Достигнув скалярного типа, невозможно спуститься дальше по иерархии типов. Скалярный тип...
0
1
105
1
Перейти к ответу Данный вопрос помечен как решенный

Ответы 1

Ответ принят как подходящий

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

Это вопрос о протоколах, а не о конкретной реализации.

Реальный вопрос: как вы синхронизируете отправку и чтение? То есть, если я отправлю сообщение узлу в вашей сети, что произойдет? Две основные идеи:

  1. Синхронный: когда я отправляю сообщение, ожидается, что все, что я прочитаю, будет ответом на это сообщение. Другими словами, последовательность ответа на запрос выглядит следующим образом: Req1 -> Resp1 -> Req2 -> Resp2 и т. д. Вы также можете передавать запросы, т. е. Req1 -> Req2 -> Resp1 -> Resp2. Но несинхронизированные ответы не допускаются, например. это неверно: Req1 -> Req2 -> Resp2 -> Resp1. Этот синхронный подход широко используется в протоколе HTTP.

  2. Асинхронный: с каждым сообщением я отправляю уникальный идентификатор, и все, что я читаю, также должно иметь идентификатор. Затем я сопоставляю ответ с запросом по идентификатору. При таком подходе действительно возможна следующая последовательность: Req1 -> Req2 -> Resp2 -> Resp1.

Что можно сделать при синхронном подходе по тайм-ауту? Вы все еще можете дождаться ответа, а затем отбросить его (с журналом), но это задержит каждый другой запрос из-за синхронного характера. И если партнер противен, это может привести к бесконечному ожиданию, и в конечном итоге у вас закончатся ресурсы. В качестве альтернативы вы можете просто закрыть соединение. Это безопаснее и проще, и часто это то, что выбирают разработчики.

При асинхронном подходе вы удаляете идентификатор из своей «карты обработчика идентификатора к ответу» (которую вы все равно должны поддерживать), и все. И не забудьте отбросить ответы без совпадения идентификатора (с журналом). Конечно, в конечном итоге вы также захотите закрыть неприятные связи.

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

Это асинхронно. Идея в том, что я отправляю req1, устанавливаю тайм-аут и, скажем, я читаю только половину сообщения (res1) за это время. Затем я намерен отказаться от него, поскольку будет отправлено новое сообщение (res1). Но мой async_read_some() все еще читает первый, верно? И я хочу снова прочитать в новый буфер. Но я, наверное, что-то неправильно понял, я совсем новичок в этом.

user680891 10.12.2020 10:36

@ user680891 async_read_some() читает данные. Он не осознает, является ли он первым, вторым, третьим или кем-то еще. Он читает поток. Вам решать интерпретировать входящие байты, являются ли они все тем же сообщением или, возможно, уже следующим. Также я настоятельно рекомендую сбрасывать тайм-аут всякий раз, когда вы читаете сообщение. Различить, является ли это новым сообщением или продолжением предыдущего, может быть слишком сложно.

freakish 10.12.2020 11:07

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

user680891 10.12.2020 11:15

Другие вопросы по теме