Структура программы для двунаправленной связи TCP с использованием Boost :: Asio - PullRequest
12 голосов
/ 24 июня 2011

Прежде всего, я надеюсь, что мой вопрос имеет смысл и даже возможен! Из того, что я читал о TCP-сокетах и ​​Boost :: ASIO, я думаю, что так и должно быть.

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

Первая сбивающая с толку часть о TCP (/ IP?) Заключается в том, что ему требуется эта модель клиент / сервер. Тем не менее, чтение показывает, что любая из сторон способна писать или читать, поэтому я еще не совсем обескуражен. Я не против установить произвольную сторону в качестве клиента, а другую - в качестве сервера. В моем заявлении об этом можно договориться заранее, и это меня не касается.

К сожалению, все примеры, с которыми я сталкиваюсь, сосредоточены на клиенте, подключающемся к серверу, и на сервере, немедленно отправляющем часть данных обратно. Но я хочу, чтобы клиент также мог писать на сервер.

Я представляю какой-то цикл, в котором я называю io_service.poll(). Если опрос показывает, что другая сторона ожидает отправки некоторых данных, она вызовет read() и примет эти данные. Если в очереди ничего нет, и у него есть данные для отправки, он вызовет write(). При этом обе стороны должны уметь читать и писать друг другу.

Меня интересует, как избежать ситуаций, когда оба одновременно выполняют какую-либо синхронную операцию записи (). У них обоих есть данные для отправки, и они сидят там в ожидании отправки их с обеих сторон. Означает ли эта проблема, что я должен делать только асинхронные write() и read()? В этом случае произойдет ли взрыв, если обе стороны соединения попытаются одновременно выполнить асинхронную запись?

Я надеюсь, что в идеале кто-то может:

1) Обеспечить структуру очень высокого уровня или лучший метод подход, который мог бы выполнить эту задачу с точки зрения клиента и сервера

или, несколько менее идеально,

2) Скажите, что то, что я пытаюсь сделать, невозможно, и, возможно, предложите какой-то обходной путь.

Ответы [ 4 ]

3 голосов
/ 24 июня 2011

То, что вы хотите сделать, абсолютно возможно.Веб-трафик является хорошим примером ситуации, когда «клиент» отправляет что-то задолго до того, как это делает сервер.Я думаю, что вас сбивают с толку слова "клиент" и "сервер".

Что на самом деле описывают эти слова, так это метод установления соединения.В случае «клиента» это «активное» учреждение;в случае «сервера» это «пассивно».Таким образом, вам может показаться менее сложным использовать термины «активный» и «пассивный» или, по крайней мере, думать о них таким образом.

В отношении поиска примера кода, который вы можете использовать в качестве основы для своегоВ работе, я настоятельно рекомендую вам взглянуть на книгу У. Ричарда Стивенса "Unix Network Programming".Любого издания будет достаточно, хотя второе издание будет более актуальным.Это будет только C, но ничего страшного, потому что API сокетов - только C.boost :: asio - это хорошо, но звучит так, что вам может быть полезно увидеть некоторые гайки и болты под капотом.

2 голосов
/ 24 июня 2011

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

Похоже, вы несколько запутались в том, как используются протоколы. TCP обеспечивает только надежный поток байтов, не более того. Кроме того, приложения используют протокол, чтобы знать, когда и сколько данных нужно читать и записывать. И клиент, и сервер, записывающие данные одновременно, могут привести к тупику, если ни одна из сторон не читает данные. Одним из способов решения этой проблемы является использование deadline_timer для отмены асинхронной операции записи, если она не завершена в течение определенного периода времени.

При написании сервера вы должны использовать асинхронные методы. Синхронные методы подходят для некоторых тривиальных клиентских приложений.

1 голос
/ 24 июня 2011

TCP является полнодуплексным, то есть вы можете отправлять и получать данные в нужном вам порядке. Чтобы предотвратить взаимную блокировку в вашем собственном протоколе (поведение вашей программы на высоком уровне), когда у вас есть возможность отправлять и получать, вы должны получать в качестве приоритета. С epoll в режиме триггера уровня, который выглядит следующим образом: epoll для отправки и получения, если вы можете получать, то делайте это, в противном случае, если вы можете отправить и что-то отправить, сделайте это. Я не знаю, как Boost :: Asio или темы подходят здесь; вам нужно определенное количество контроля над тем, как чередуются отправка и получение.

0 голосов
/ 24 июня 2011

Слово, которое вы ищете, это «неблокирующее», которое полностью отличается от асинхронного ввода-вывода POSIX (который включает сигналы).

Идея состоит в том, что выиспользуйте что-то вроде fcntl(fd,F_SETFL,O_NONBLOCK).write() вернет количество успешно записанных байтов (если оно положительное), и оба значения read() и write() вернут -1 и установят errno = EAGAIN, если "прогресс не может быть достигнут" (нет данных для чтения или записи полного окна).

Затем вы используете что-то вроде select / epoll / kqueue, которое блокирует, пока сокет не будет доступен для чтения / записи (в зависимости от установленных флагов).

...