|
4 / 4 / 2
Регистрация: 13.11.2014
Сообщений: 108
|
|||||||||||||||||||||
Потеря части больших данных при приёме через recv17.04.2023, 16:10. Показов 5485. Ответов 3
Есть небольшой сервер на C++ кросплатформенный с поддержкой SSL (там собстно 2 порта ssl и без него), на неблокирующих сокетах epoll, который всё больше и больше разрастается. Разбирает себе HTTP заголовок, на точки входа, парсит json, что-то там добавляет в базу и т.д. и т.п.
Всё работает всё хорошо, НО теперь встала задача по приёму в POST'е тупо большого json'а. Он достаточно прост, вот пример:
Собственно проблема в самом заголовке, а сейчас опишу чего и как делал, что пробовал и т.д. Элементарно while для recv на приёме: Кликните здесь для просмотра всего текста
На Windows всё работает отменно (код при этом собирается в VS 2019), хоть 100 тысяч записей отошли, всё нормально. А вот на CentOS7 собираю в g++ с стандартом C++14 языка и всё и трында( У нас recv однажды получает 0 из стека TCP и всё мы отваливаемся и не дочитываем данные. Порылся в интернете, аага, ok, у нас в стеке могут быть данные не сразу все, мб обрыв соединения или ещё что, т.е. прилетает себе вполне 0, а вот дальше идут ещё пакеты... и это не смотря на sleep_for который я прописывал, чтоб их дожидаться в стеке.... нуу ok, пробуем так Пробовал уже и: Кликните здесь для просмотра всего текста
Но ниит( ето не прокатывает, пробуем и if (nDataLength >= 0) проставить и с таймера поиграться, всё тленн( В процессе перепробовал уже всё что только можно я и MTU размеры пакета вычислял по самое не хочу и Content-Length анализировал, вообще чем только не страдал, вкорячивал и вовсе вот такую достаточно длинную и оптимизированную функцию для поиска списка кратных чисел размера пакета: Кликните здесь для просмотра всего текста
По которой вообще брал делители от 200 до 3000 и по их ряду определял пришёл нам оборванный пакет можно выходить с чтения, либо это что-то целостное и надо бы его ещё и проанализировать на Content-Length закончился ли размер. По итогу и эту затею отмёл, т.к. я и вовсе не 0 ловил, а -1 и всё и происходил выход, так и не получив нормально всех данных. Т.е. там вообще имеем вариант с while (count_bad_read_recv <= 3) более предпочтительный. Честно говоря это уже сводит меня с ума( Я смотрел исходники nginx и libmicrohttpd, там вообще всё это дело гораздо проще, nginx мб ещё и живёт в своих простанствах имён и я чего не понял, но в libmicrohttpd элементарно тупо мой первый вариант и всё. Ну и что ему может не нравиться? P.S. есть дефолтный проект, если что могу скинуть, но там как бы всё одно и тоже.
0
|
|||||||||||||||||||||
| 17.04.2023, 16:10 | |
|
Ответы с готовыми решениями:
3
Потеря части данных при отправке через TSocket ARM11. Потеря данных при приеме UART-ом Зависает при приёме больших данных |
|
COM‐пропагандист
|
||
| 18.04.2023, 08:00 | ||
|
Если вам recv вернула ноль, это значит что вы достигли конца потока байтов и другая сторона закрыла соединение. Единственное, что вам остаётся делать в этой ситуации — тоже закрыть сокет со своей стороны. Не пытайтесь читать байты из закрытого с той стороны сокета.
Добавлено через 11 минут У метода POST всегда должно быть тело запроса. 1. Анализируем заголовки и ищем Content-Length. Если такого заголовка нет, то сразу отправляем ошибку 411 Length Required и закрываем соединение. 2. Выделаем память под массив размером, указанным в заголовке Content-Length (или место на диске, если размер длинный). 3. Делаем в цикле recv до тех пор пока не получим весь Content-Length.
0
|
||
|
4 / 4 / 2
Регистрация: 13.11.2014
Сообщений: 108
|
|||||||
| 18.04.2023, 10:59 [ТС] | |||||||
|
Мнение по поводу нуля я вычитал . Ни в коем случае не претендую на конечную истинность высказанных там выражений)
Просто есть мнение и я решил и его проверить в том числе. А посему анализ контента уже следует делать аж после приёма сообщения как такового и уже отдавать 411 или чего-то там ещё. А вообще вот такая конструкция мне даже больше понравилась: Кликните здесь для просмотра всего текста
И надо сказать это прям работает на 100% и можно закрывать тему) НО либо я дурачок, либо лыжи не едут XD Короче оказалось при большом количестве клиентов на которых я постоянно и тестировал у меня постоянно "вылетал стэк сокета", либо ещё что-то в этом роде. Но на одном всё работает стабильно. Да даже если 2 параллельно запустить. А пускаю третьего он уже ловит висяк на рэндомной отправке скажем в 900 записей, при этом они не записываются никак. Закрываем всё это дело, Опять запускаю отправку теперь уже допустим на 4к записей, опять висяк, НО в это время на сервер приходят полные себе 900 записей предыдущих вместо 4к. Опять закрываю, пускаю снова, снова висим, зато теперь приходят обрезанные 4к записей, вместо скажем 2к, что должны были отправиться, нуу и т.д. по кругу. Короче я по ходу где-то накосячил с передачей сокета в класс клиента... они то там у меня ещё и map'ятся, короче эт мне теперь надолго разбираться) ...хотяя странно т.к. до этого просто делал с расчётом на постоянный MTU (а потом приобрёл кучу знаний о том на сколько он может быть различный то в мировой сети ) и вообще у 20 клиентов таких проблем не было.В общем буду разбираться, но если у кого какие умные мысли возникнут, то welcome) Добавлено через 3 минуты хммм а ссылки на другой форум запрещены?) нуу тогда мнение по поводу 0 я вычитал отсюда - ru_stackoverflow_com/ questions/ 442794/%D0%9A%D0%B0%D0%BA-%D0%BE%D0%BF%D1%80%D0%B5%D0%B4%D0%B5%D0% BB%D0%B8%D1%82%D1%8C-%D0%BA%D0%BE%D0%BD%D0%B5%D1%86-%D0%BF%D0%BE%D1%81%D1%8B%D0%BB%D0%BA%D0% B8-%D0%BF%D0%BE-%D1%81%D0%BE%D0%BA%D0%B5%D1%82%D0%B0%D0% BC
0
|
|||||||
|
COM‐пропагандист
|
||
| 18.04.2023, 14:49 | ||
Если соединение было корректно закрыто, возвращаемое значение равно нулю. https://learn.microsoft.com/en... nsock-recv Пришло 0 байт = соединение закрыто. Это конец потока. Нет никакого смысла читать из потока, когда вы достигли конца. То же самое как нет никакого смысла читать из файла, когда вы достигли End Of File. Всё что вам остаётся делать — закрыть сокет со своей стороны.
0
|
||
| 18.04.2023, 14:49 | |
|
Помогаю со студенческими работами здесь
4
Потеря части данных при извлечении поля из БД Ошибка при приеме данных через COM (Arduino-Xbee-PC) Дублирование данных при приеме файла через сокет Нечитаемый текст при приеме данных через COM PORT RS 232 Обновление элемента label при приёме данных через serialport Искать еще темы с ответами Или воспользуйтесь поиском по форуму: |
|
Новые блоги и статьи
|
|||
|
Символьное дифференцирование
igorrr37 13.02.2026
/ *
Логарифм записывается как: (x-2)log(x^2+2) - означает логарифм (x^2+2) по основанию (x-2).
Унарный минус обозначается как !
в-строка - входное арифметическое выражение в инфиксной(обычной). . .
|
Камера Toupcam IUA500KMA
Eddy_Em 12.02.2026
Т. к. у всяких "хикроботов" слишком уж мелкий пиксель, для подсмотра в ESPriF они вообще плохо годятся: уже 14 величину можно рассмотреть еле-еле лишь на экспозициях под 3 секунды (а то и больше),. . .
|
И ясному Солнцу
zbw 12.02.2026
И ясному Солнцу,
и светлой Луне.
В мире
покоя нет
и люди
не могут жить в тишине.
А жить им немного лет.
|
«Знание-Сила»
zbw 12.02.2026
«Знание-Сила»
«Время-Деньги»
«Деньги -Пуля»
|
|
SDL3 для Web (WebAssembly): Подключение Box2D v3, физика и отрисовка коллайдеров
8Observer8 12.02.2026
Содержание блога
Box2D - это библиотека для 2D физики для анимаций и игр. С её помощью можно определять были ли коллизии между конкретными объектами и вызывать обработчики событий столкновения. . . .
|
SDL3 для Web (WebAssembly): Загрузка PNG с прозрачным фоном с помощью SDL_LoadPNG (без SDL3_image)
8Observer8 11.02.2026
Содержание блога
Библиотека SDL3 содержит встроенные инструменты для базовой работы с изображениями - без использования библиотеки SDL3_image. Пошагово создадим проект для загрузки изображения. . .
|
SDL3 для Web (WebAssembly): Загрузка PNG с прозрачным фоном с помощью SDL3_image
8Observer8 10.02.2026
Содержание блога
Библиотека SDL3_image содержит инструменты для расширенной работы с изображениями. Пошагово создадим проект для загрузки изображения формата PNG с альфа-каналом (с прозрачным. . .
|
Установка Qt-версии Lazarus IDE в Debian Trixie Xfce
volvo 10.02.2026
В общем, достали меня глюки IDE Лазаруса, собранной с использованием набора виджетов Gtk2 (конкретно: если набирать текст в редакторе и вызвать подсказку через Ctrl+Space, то после закрытия окошка. . .
|