Я реализую простой сервер, который принимает одно соединение, а затем использует этот сокет для одновременного чтения и записи сообщений из потоков чтения и записи.
Какой безопасный и простой способ одновременно читать и писать из одного и того же дескриптора сокета в c / c ++ в linux?
Мне не нужно беспокоиться о множественном чтении и записи из одного и того же сокета, так как в сокет будет записано одно выделенное чтение и один выделенный поток записи.
В приведенном выше сценарии требуется ли какой-либо вид блокировки?
Требует ли приведенный выше сценарий неблокирующий сокет?
Есть ли какая-нибудь библиотека с открытым исходным кодом, которая поможет в приведенном выше сценарии?
В приведенном выше сценарии требуется ли какой-либо вид блокировки?
Никто.
Требует ли приведенный выше сценарий неблокирующий сокет?
Бит, который вас, вероятно, беспокоит — потоки чтения и записи в установленном соединении — не обязательно должны быть неблокирующими, если вы счастливы, что эти потоки ожидают завершения. Обычно это одна из причин, по которой вы будете использовать потоки, а не операции выбора, опроса или асинхронные операции … и код будет проще.
Если поток, принимающий новых клиентов, будет рад заблокировать вызов accept()
тогда тебе там тоже хорошо.
Тем не менее, есть одна тонкая проблема с TCP-серверами, которую вы, возможно, захотите оставить в своем уме … если ваша программа расширяется для работы с несколькими клиентами и требует некоторого периодического обслуживания. Естественно и заманчиво использовать select
оператор с таймаутом для проверки читабельности на слушающем сокете — который указывает на попытку подключения клиента — затем accept
связь. Там есть условие гонки: попытка подключения к клиенту могла прерваться между select()
а также accept()
, в таком случае accept()
будет блокировать, если прослушивающий сокет не является неблокирующим, и это может помешать своевременному возвращению к select()
Зацикливание и остановка периодической обработки по тайм-ауту, пока другой клиент не соединится
Есть ли какая-нибудь библиотека с открытым исходным кодом, которая поможет в приведенном выше сценарии?
Существуют сотни библиотек для написания базовых серверов, но в конечном итоге то, что вы просили, легко достигается с помощью предоставляемых ОС сокетов BSD или их подстройки под Windows.
Розетки двунаправленные. Если вы когда-либо прорезали кабель Ethernet или последовательный кабель или видели для них низкоуровневую схему подключения оборудования, вы можете на самом деле увидеть отдельные медные провода для линий «TX» (передача) и «RX» (прием). Программное обеспечение для отправки сигналов от контроллера устройства до большинства API-интерфейсов ОС для «сокета» отражает это, и это является ключевым отличием между сокетом и обычным каналом в большинстве систем (например, Linux).
Чтобы по-настоящему использовать все возможности сокетов, вам необходимо:
1) Поддержка асинхронного ввода-вывода, использующая порты завершения ввода-вывода, epoll () или некоторую аналогичную асинхронную функцию обратного вызова или систему событий для «пробуждения» при поступлении данных в сокет. Затем он должен вызвать ваш API-интерфейс «ReadData» самого низкого уровня, чтобы прочитать сообщение из сокетного соединения.
2) 2-й API, который поддерживает низкоуровневые записи, «WriteData» (передача), который помещает байты в сокет и не зависит от того, что нужно логике «ReadData». Помните, что отправка и получение независимы даже на аппаратном уровне, поэтому не вводите блокировку или другую синхронизацию на этом уровне.
3) Пул потоков Socket IO, которые вслепую выполняют любую обработку данных, которые считываются или будут записаны в сокет.
4) ПРОТОКОЛ CALLBACK: объект обратного вызова, на который потоки сокета имеют умные указатели. Он обрабатывает любой уровень PROTOCOL, например, анализирует ваш большой двоичный объект в реальном HTTP-запросе, который находится поверх основного соединения с сокетом. Помните, что сокет — это просто канал передачи данных между компьютерами, и данные, передаваемые по нему, часто поступают в виде серии фрагментов — пакетов. В таких протоколах, как UDP, пакеты даже не в порядке. Низкоуровневые «ReadData» и «WriteData» будут вызывать обратные вызовы из своих потоков сюда, потому что именно там фактически начинается обработка данных с учетом содержимого.
5) Любые обратные вызовы, в которых нуждается сам обработчик протокола. Для HTTP вы упаковываете необработанные буферы запросов в красивые объекты, которые вы передаете реальному сервлету, который должен возвращать хороший объект ответа, который можно сериализовать в ответ, соответствующий спецификации HTTP.
Обратите внимание на базовый шаблон: вы должны сделать всю систему в целом асинхронной («обратный вызов»), если вы хотите в полной мере использовать двунаправленный асинхронный ввод-вывод по сравнению с сокетами. Единственный способ одновременного чтения и записи в сокет — это потоки, так что вы все равно можете синхронизировать потоки «писатель» и «читатель», но я бы сделал это только в том случае, если протокол или другие соображения потребовали бы мою руку. Хорошая новость заключается в том, что вы можете добиться высокой производительности с сокетами, используя высоко асинхронную обработку, а плохая в том, что создание такой системы надежным способом — серьезное усилие.
Вам не нужно беспокоиться об этом. Один поток чтения и один поток записи будет работать, как вы ожидаете. Сокеты полнодуплексные, поэтому вы можете читать, пока пишете, и наоборот. Вам придется беспокоиться, если у вас есть несколько авторов, но это не так.