Существует ли функция для определения того, сколько байтов осталось для чтения в доменном сокете unix?

#linux #c 17 #ipc #json-rpc #unix-socket

#linux #c 17 #ipc #json-rpc #unix-сокет

Вопрос:

Цель — взаимодействовать с сервером OpenEthereum с использованием json-rpc.

Проблема в том, что после подключения мне нужно реагировать только при получении данных, поскольку целью является подписка на событие, поэтому мне нужно recv() , чтобы функция блокировалась. Но в этом случае, если я попрошу прочитать в буфере больше, чем сервер отправил, запрос будет заблокирован.

Сервер OpenEthereum разделяет свои запросы n символом перевода строки, но я не знаю, как это может помочь.
Я знаю о простом ожидании recv() тайм-аута. Но я использую C и ipc для лучшей задержки, чем мои конкуренты по арбитражу.Это также означает, что мне нужно иметь как можно меньшее количество переключений контекста.

Как эффективно прочитать сообщение, длина которого не может быть определена заранее?

Комментарии:

1. Что такое receive ? Вы случайно имеете в виду recv или recvmsg ?

2. На вашем месте я бы использовал bosst asio, в частности, с функцией async . Поскольку они действительно эффективны. Если вы решили использовать сокеты unix, я рекомендую вам прочитать «Руководство Beej по сетевому программированию» beej.us/guide/bgnet/html .

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

4. @V0_1D на самом деле это не сетевое программирование. Как уже объяснялось, это json rpc через ipc, а не через tcp. Вот почему мне не удалось найти пример и никакой информации, поддерживают ли функции домена boost unix получение только того, что было записано в сокете до сих пор (ни больше, ни меньше). Неужели нет современного c для решения такой проблемы в потоках?

5. @Бесполезно вот почему я написал I need to react only when receving data as the aim is to subscribe to an event so I need the recv() function to be blocking в вопросе.

Ответ №1:

Существует ли функция для определения того, сколько байтов осталось для чтения в доменном сокете unix?

Нет — просто продолжайте выполнять неблокирующие чтения, пока не будет возвращено EAGAIN или EWOULDBLOCK .

Может быть специфичный для платформы ioctl или fcntl — но вы не назвали платформу, и она не переносима и не нужна.

Как эффективно прочитать сообщение, длина которого не может быть определена заранее?

Просто выполните неблокирующее чтение в буфер, достаточно большой, чтобы содержать самое большое сообщение, которое вы можете получить.

Мне нужно реагировать только при получении данных, поскольку целью является подписка на событие, поэтому мне нужна функция recv () для блокировки

Вы путаете две вещи.

  1. Как получать уведомления, когда сокет становится доступным для чтения:

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

  2. Как прочитать все, что доступно для чтения, без блокировки на неопределенный срок:

    выполняя неблокирующие чтения до EWOULDBLOCK EAGAIN тех пор, пока не будет возвращено или.

Логически существует третий шаг для подобных потоковых протоколов, который заключается в правильном управлении буферами в случае частичных сообщений. О, и на самом деле разбор сообщений, но я предполагаю, что у вас уже есть библиотека JSON.

Это совершенно нормальный, базовый дизайн ввода-вывода UNIX. Это не экзотическая оптимизация.

Комментарии:

1. Я добавил Linux в теги до того, как вы опубликовали этот ответ. Что касается переносимости, код не будет раскрыт конкурентам.

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

3. С точки зрения производительности, я вижу самый быстрый даже для одного соединения kqueue() , но мне не удается найти пример для домена Unix, который, насколько я понимаю, не использует дескрипторы файлов для сокетов.

4. У вашего IPC-транспорта есть путь, что означает, что это почти наверняка сокет домена UNIX, в частности, ориентированный на поток сокет с адресом AF_UNIX. Для большинства целей он работает идентично TCP-сокету в интерфейсе обратной связи. Все сокеты используют файловые дескрипторы, включая этот.

5. Верно, но вызов ioctl в цикле занятости намного дороже, чем просто использование select или poll, которые на самом деле предназначены для этой цели. Почему вы так стремитесь найти другой способ дождаться, пока сокет станет доступным для чтения?