Я работаю над встроенной системой с Linux. Клиентский поток записывает некоторые данные в сокет, но то, что серверный поток читает на другой стороне, отличается от того, что было записано. Что вызывает сбой потока (и родительского процесса).
Я новичок в сетях и Linux. Я сбросил каждую часть данных, которые записываются, все в порядке.
Трассировка функции в gdb показывает следующую информацию.
(gdb)
#0 0x00007f62be8e8670 in getenv () from /lib/libc.so.6
#1 0x00007f62be92057a in __libc_message () from /lib/libc.so.6
#2 0x00007f62be99f927 in __fortify_fail () from /lib/libc.so.6
#3 0x00007f62be99f8f0 in __stack_chk_fail () from /lib/libc.so.6
#4 0x0000000000406471 in reading (sockFd=15) at __line_number_in_the_program__
#5 0x793bcf318b18bb01 in ?? ()
#6 0x117d0300942ff567 in ?? ()
#7 0x0000000100000000 in ?? ()
..
..
..
Он идет до #785 с каким-то [случайным] адресом.
read() — это функция, которая обрабатывает прочитанные данные в потоке сервера.
Я подозреваю, что что-то не так внутри сокета. Есть ли способ увидеть данные, которые находятся в буфере сокетов (клиент/сервер), не читая их? Или любой другой способ отладить его с помощью gdb?
Уже есть некоторые проверки для правильной обработки прочитанных данных, но они тоже не помогают.
Если это сокеты AF_INET или AF_INET6 (TCP или UDP), то такие инструменты, как Wireshark и Скрипач, чрезвычайно полезны для отладки этого типа проблем. Wireshark позволяет вам видеть, что происходит в пакетах. Fiddler полезен, если ваш протокол основан на HTTP и может отображать полную историю запросов/ответов даже для зашифрованных соединений HTTPS.
Внутри сокета почти наверняка ничего не происходит. Хотя технически возможно, что вы обнаружили ошибку в ядре Linux, помните, что Linux используется на сотнях миллионов машин, и большинство из них зависит от сети. Таким образом, шанс найти ошибку, которая изменяет данные внутри сокета, очень маловероятен. Шанс, что вы допустили ошибку в своем собственном коде, весьма вероятен.
Спасибо, @PhilipCouling. Использование Wireshark было хорошей идеей. Я проверю это, если это поможет. Поскольку связь происходит на локальном хосте, будет использоваться Wireshark с петлевым адресом. Я также признаю ваш второй комментарий.
Да, есть. Ищите MSG_PEEK
флаг recv(2)
. Полезно ли это для отладки вашей программы — совсем другой вопрос, и это весьма сомнительно. Ваш «сервер» должен иметь возможность обрабатывать искаженные данные вместо того, чтобы идти в рекурсивное путешествие или взрывать стек, как это, по-видимому, происходит.
Я голосую за закрытие этого вопроса, потому что на него, похоже, ответили. В комментариях и ответ.
Опубликуйте минимальный воспроизводимый пример вашего сервера и клиента, чтобы мы могли воспроизвести проблему и помочь вам отладить ее.
У вас проблема с переполнением буфера стека. Если вы никогда не слышали о средстве защиты стека GCC, сейчас самое время узнать о нем. Хотя Wireshark — очевидный инструмент для просмотра данных в полете, это не является источником вашей проблемы. Ваш сервер должен быть защищен от любых вредоносных данных, считываемых из сети. Это базовая практика проектирования и реализации серверов. У вас проблема с переполнением буфера стека.
Это, конечно, то, что нужно исправить, но обязательно ответ на вопрос. ОП считает, что сбой вызван неправильными полученными данными. Программа-получатель определенно должна избегать ошибок переполнения стека при получении и анализе неверных данных (да), но защита от этого не решит проблему, если отправитель отправляет неверные данные.
Нет, буфер отправки/получения сокета управляется ядром и не может быть открыт для пользовательского пространства, в противном случае возникла бы проблема безопасности ядра Linux.