Подтвердить что ты не робот

Одновременно читать и писать в одном и том же сокете на C или С++

Я реализую простой сервер, который принимает одно соединение, а затем использует этот сокет для одновременного чтения и записи сообщений из потоков чтения и записи. Каков безопасный и простой способ одновременного чтения и записи из одного и того же дескриптора сокета в c/С++ на linux? Мне не нужно беспокоиться о чтении и записи нескольких потоков из одного и того же сокета, поскольку в сокет будет входить один выделенный поток чтения и одиночный выделенный поток записи.

В приведенном выше сценарии требуется какой-либо блокировки?

Требуется ли в вышеупомянутом сценарии неблокирующий сокет?

Есть ли библиотека с открытым исходным кодом, которая поможет в приведенном выше сценарии?

4b9b3361

Ответ 1

В приведенном выше сценарии требуется какой-либо блокировки?

Отсутствует.

Требуется ли в вышеупомянутом сценарии неблокирующий сокет?

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

Если поток, принимающий новых клиентов, рад заблокировать в вызове accept(), тогда вы тоже хорошо там.

Тем не менее, есть одна тонкая проблема с TCP-серверами, которые вы, возможно, захотите сохранить в своем сознании... если ваша программа растет, чтобы обрабатывать несколько клиентов и выполнять некоторую периодическую работу. Естественно и заманчиво использовать инструкцию select с таймаутом для проверки на удобочитаемость в прослушивающем сокете - что указывает на попытку подключения клиента, а затем accept соединение. Там есть условие гонки: попытка подключения клиента может упасть между select() и accept(), и в этом случае accept() будет блокировать, если прослушивающий сокет не будет блокировать, и это может помешать своевременному возврату в select() и остановите периодическую обработку по времени, пока не подключится другой клиент.

Есть ли библиотека с открытым исходным кодом, которая поможет в приведенном выше сценарии?

Существует сотни библиотек для написания базовых серверов, но в конечном итоге то, что вы просили, легко достигается на OS-предоставляемых сокетах BSD или их подсистеме Windows.

Ответ 2

Сокеты BI-DIRECTIONAL. Если вы когда-либо на самом деле разбирали кабель Ethernet или Serial или видели для них схему подключения к низкоуровневому оборудованию, на самом деле вы можете увидеть отдельные медные провода для линий передачи "TX" (передача) и "RX" (прием). Программное обеспечение для отправки сигналов от контроллера устройства до большинства OS API для "сокета" отражает это, и это ключевое различие между сокетом и обычным каналом в большинстве систем (например, Linux).

Чтобы получить максимальную отдачу от сокетов, вам необходимо:
1) Поддержка Async IO, которая использует IO Completion Ports, epoll() или некоторую аналогичную систему обратного вызова асинхронного вызова или события для "пробуждения", когда данные поступают в сокет. Затем этот вызов должен вызывать ваш API-интерфейс "ReadData" вашего нижнего уровня, чтобы прочитать сообщение от соединения сокета.
2) Второй API, поддерживающий низкоуровневую запись, "WriteData" (передача), которая толкает байты в сокет и не зависит от чего-либо, что требуется логике "ReadData" . Помните, что ваша передача и получение независимы даже на аппаратном уровне, поэтому не вводите блокировку или другую синхронизацию на этом уровне.
3) Пул потоков Socket IO, который слепо обрабатывает данные, которые считываются или записываются в сокет.
4) PROTOCOL CALLBACK: объект обратного вызова, к которому подключаются потоки сокетов. Он обрабатывает любой слой PROTOCOL, такой как разбор данных blob в реальном HTTP-запросе, который находится поверх основного сокетного соединения. Помните, что сокет - это всего лишь канал данных между компьютерами и переданные по нему данные, которые часто поступают в виде серии фрагментов - пакетов. В таких протоколах, как UDP, пакеты даже не в порядке. Низкоуровневые "ReadData" и "WriteData" будут обращать внимание на их потоки, потому что именно на самом деле начинается обработка информации с содержанием.
5) Любые обратные вызовы, которые сам обработчик протокола. Для HTTP вы помещаете необработанные буферы запросов в красивые объекты, которые вы передаете реальному сервлету, который должен возвращать хороший объект ответа, который может быть сериализован в HTTP-совместимый ответ.

Обратите внимание на базовый шаблон: вы должны сделать всю систему принципиально асинхронной ( "лук обратных вызовов" ), если вы хотите в полной мере использовать двунаправленные, асинхронные IO-сокеты. Единственный способ одновременного чтения и записи в сокет - это потоки, поэтому вы все равно можете синхронизировать поток "писатель" и "читатель", но я бы сделал это, только если протокол или другие соображения заставили мою руку. Хорошей новостью является то, что вы можете получить отличную производительность с помощью сокетов с использованием высокоасинхронной обработки, плохое в том, что создание такой системы надежным способом - это серьезное усилие.

Ответ 3

Вам не о чем беспокоиться. Одно чтение потока и одно нить записи будут работать, как вы ожидаете. Сокеты имеют полный дуплекс, поэтому вы можете читать, пока вы пишете, и наоборот. Вы должны были бы беспокоиться, если бы у вас было несколько авторов, но это не тот случай.